ScaleRocket/Mobile

Chargement

ActivityIndicator, écrans squelette et configuration de l'écran de démarrage pour les états de chargement.

Chargement

ScaleRocket Mobile fournit plusieurs patterns de chargement pour différents contextes — spinners en ligne, placeholders squelette et écran de démarrage initial.

ActivityIndicator

L'état de chargement le plus simple utilise l'ActivityIndicator intégré de React Native :

import { ActivityIndicator, View } from "react-native";

function LoadingScreen() {
  return (
    <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
      <ActivityIndicator size="large" color="#3B82F6" />
    </View>
  );
}

Utilisez la version thémée pour la cohérence :

import { Loading } from "@/components/ui/Loading";

// Chargement plein écran
<Loading />

// Chargement en ligne avec texte
<Loading size="small" message="Saving..." />

Wrapper de chargement

Enveloppez les écrans dépendant de données avec un garde de chargement :

import { Loading } from "@/components/ui/Loading";

export default function DashboardScreen() {
  const { data, isLoading } = useQuery();

  if (isLoading) return <Loading />;

  return (
    <ScreenLayout>
      <Text>{data.title}</Text>
    </ScreenLayout>
  );
}

Écrans squelette

Les écrans squelette offrent une meilleure expérience utilisateur que les spinners en montrant la forme de la mise en page pendant le chargement :

import { View, StyleSheet } from "react-native";
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withRepeat,
  withTiming,
} from "react-native-reanimated";

function SkeletonBox({ width, height }: { width: number; height: number }) {
  const opacity = useSharedValue(0.3);

  React.useEffect(() => {
    opacity.value = withRepeat(withTiming(1, { duration: 800 }), -1, true);
  }, []);

  const animatedStyle = useAnimatedStyle(() => ({
    opacity: opacity.value,
  }));

  return (
    <Animated.View
      style={[
        { width, height, backgroundColor: "#E5E7EB", borderRadius: 8 },
        animatedStyle,
      ]}
    />
  );
}

Utilisez les squelettes pour refléter la vraie mise en page :

function CardSkeleton() {
  return (
    <View style={{ padding: 16, gap: 12 }}>
      <SkeletonBox width={120} height={16} />
      <SkeletonBox width={200} height={32} />
      <SkeletonBox width={160} height={14} />
    </View>
  );
}

function DashboardSkeleton() {
  return (
    <ScreenLayout>
      <CardSkeleton />
      <CardSkeleton />
      <CardSkeleton />
    </ScreenLayout>
  );
}

Tirer pour rafraîchir

Ajoutez le tirer-pour-rafraîchir sur les écrans de liste :

import { RefreshControl, FlatList } from "react-native";

function ItemList() {
  const [refreshing, setRefreshing] = useState(false);

  const onRefresh = async () => {
    setRefreshing(true);
    await refetchData();
    setRefreshing(false);
  };

  return (
    <FlatList
      data={items}
      renderItem={({ item }) => <ItemRow item={item} />}
      refreshControl={
        <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
      }
    />
  );
}

Écran de démarrage

Configurez l'écran de démarrage dans app.json :

{
  "expo": {
    "splash": {
      "image": "./assets/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    }
  }
}

Gardez l'écran de démarrage visible pendant le chargement des données initiales :

import * as SplashScreen from "expo-splash-screen";

SplashScreen.preventAutoHideAsync();

export default function RootLayout() {
  const { isLoading } = useSession();

  useEffect(() => {
    if (!isLoading) {
      SplashScreen.hideAsync();
    }
  }, [isLoading]);

  if (isLoading) return null;

  return <Slot />;
}

Quand utiliser quoi

ContextePattern
Chargement initial de l'appÉcran de démarrage
Chargement de données d'écranÉcran squelette
Action de boutonActivityIndicator dans le bouton
Rafraîchissement de listeTirer pour rafraîchir
Sauvegarde en arrière-planNotification toast à la fin

On this page