ScaleRocket/Mobile

Toast

Notifications toast et alertes sur mobile avec Alert.alert() et composants toast personnalisés.

Toast

Les applications mobiles ont besoin de retour pour les actions utilisateur. ScaleRocket Mobile supporte les alertes natives et les notifications toast personnalisées.

Alerte native

L'approche la plus simple est l'Alert.alert() intégré de React Native :

import { Alert } from "react-native";

// Alerte simple
Alert.alert("Success", "Your profile has been updated.");

// Alerte avec actions
Alert.alert(
  "Delete Account",
  "Are you sure? This action cannot be undone.",
  [
    { text: "Cancel", style: "cancel" },
    { text: "Delete", style: "destructive", onPress: handleDelete },
  ]
);
PlateformeComportement
iOSDialogue modal natif
AndroidDialogue Material

Quand utiliser Alert vs Toast

ScénarioUtiliser
Confirmation destructiveAlert.alert() avec actions
Retour de succèsToast
Message d'erreurToast (non-bloquant) ou Alert (critique)
Erreur réseauToast avec action de réessai
Validation de formulaireErreurs en ligne (pas toast)

Composant Toast personnalisé

Pour les notifications non-bloquantes, utilisez un toast personnalisé :

import { useRef } from "react";
import { Animated, Text, StyleSheet } from "react-native";

interface ToastProps {
  message: string;
  type?: "success" | "error" | "info";
}

function Toast({ message, type = "info" }: ToastProps) {
  const opacity = useRef(new Animated.Value(0)).current;

  const show = () => {
    Animated.sequence([
      Animated.timing(opacity, {
        toValue: 1,
        duration: 300,
        useNativeDriver: true,
      }),
      Animated.delay(2000),
      Animated.timing(opacity, {
        toValue: 0,
        duration: 300,
        useNativeDriver: true,
      }),
    ]).start();
  };

  const colors = {
    success: "#10B981",
    error: "#EF4444",
    info: "#3B82F6",
  };

  return (
    <Animated.View
      style={[styles.toast, { opacity, backgroundColor: colors[type] }]}
    >
      <Text style={styles.text}>{message}</Text>
    </Animated.View>
  );
}

const styles = StyleSheet.create({
  toast: {
    position: "absolute",
    top: 60,
    left: 16,
    right: 16,
    padding: 16,
    borderRadius: 12,
    zIndex: 1000,
  },
  text: { color: "white", fontWeight: "600", textAlign: "center" },
});

Contexte Toast

Créez un contexte pour que n'importe quel écran puisse déclencher un toast :

import { createContext, useContext, useState, useCallback } from "react";

const ToastContext = createContext<{
  show: (message: string, type?: "success" | "error" | "info") => void;
} | null>(null);

export function ToastProvider({ children }: { children: React.ReactNode }) {
  const [toast, setToast] = useState<ToastProps | null>(null);

  const show = useCallback((message: string, type: "success" | "error" | "info" = "info") => {
    setToast({ message, type });
    setTimeout(() => setToast(null), 3000);
  }, []);

  return (
    <ToastContext.Provider value={{ show }}>
      {children}
      {toast && <Toast message={toast.message} type={toast.type} />}
    </ToastContext.Provider>
  );
}

export const useToast = () => useContext(ToastContext)!;

Utilisation depuis n'importe quel écran :

function ProfileScreen() {
  const toast = useToast();

  const handleSave = async () => {
    try {
      await saveProfile();
      toast.show("Profile saved!", "success");
    } catch {
      toast.show("Failed to save profile", "error");
    }
  };

  return <Button title="Save" onPress={handleSave} />;
}

Configuration dans le Root Layout

Enveloppez votre app avec ToastProvider :

// app/_layout.tsx
import { ToastProvider } from "@/components/ui/Toast";

export default function RootLayout() {
  return (
    <ToastProvider>
      <Slot />
    </ToastProvider>
  );
}

Toast avec action

Ajoutez un bouton annuler ou réessayer :

<Animated.View style={[styles.toast, { opacity }]}>
  <Text style={styles.text}>{message}</Text>
  {action && (
    <TouchableOpacity onPress={action.onPress}>
      <Text style={styles.action}>{action.label}</Text>
    </TouchableOpacity>
  )}
</Animated.View>

On this page