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
| Contexte | Pattern |
|---|---|
| Chargement initial de l'app | Écran de démarrage |
| Chargement de données d'écran | Écran squelette |
| Action de bouton | ActivityIndicator dans le bouton |
| Rafraîchissement de liste | Tirer pour rafraîchir |
| Sauvegarde en arrière-plan | Notification toast à la fin |