Chapitre 8
08 - React Native
08 - React Native
08 - React Native : Cours complet
Table des matières
- Architecture RN : moteurs JS, bridge
- La nouvelle architecture (TurboModules, Fabric, Hermes)
- Expo : managed workflow, EAS, dev clients
- React Navigation
- Styling : StyleSheet, NativeWind, styled-components
- Reanimated et gestures
- State management : Zustand, Redux Toolkit, React Query
- OTA updates : CodePush, Expo Updates
- Performance
- Résumé et checklist
1. Architecture RN : moteurs JS, bridge
1.1 Le principe
React Native exécute du JavaScript dans un moteur séparé et rend des composants natifs (UIView / ViewGroup). L'application a :
- le thread JS (logique, state) ;
- le thread UI natif (rendu, gestes) ;
- depuis l'architecture originale, un bridge sérialisé.
1.2 JavaScriptCore vs Hermes
| Moteur | Rôle |
|---|---|
| JavaScriptCore | Moteur historique (Safari). Premier choix, moins performant pour RN |
| Hermes | Moteur optimisé par Meta pour RN : démarrage plus rapide, moins de mémoire, bytecode précompilé |
Hermes est le défaut sur Android depuis RN 0.70 et sur iOS depuis RN 0.70+ (configurable).
1.3 Le bridge (ancienne architecture)
Diagramme en cours de génération...
Le bridge :
- sérialise les messages en JSON (coût) ;
- est asynchrone et non batching natif ;
- complique les types (objets passés par copie).
1.4 Les problèmes du bridge
- Appels lents (JSON ser/de).
- Impossibilité de passer des objets complexes.
- Fragmentation : chaque module a sa propre implémentation.
→ La nouvelle architecture les résout.
2. La nouvelle architecture
2.1 Les piliers
- TurboModules : modules natifs chargés paresseusement, avec des JSI bindings (pas de JSON).
- Fabric : système de rendu (C++), avec l'arbre de vues partagé entre JS et natif.
- JSI (JavaScript Interface) : couche C++ permettant de partager des objets natifs avec JS (types, performance).
- Codegen : génération de code C++/Java/ObjC depuis les specs TypeScript.
- Interop Layer : compatibilité avec les anciens modules (bridge).
2.2 Schéma nouvelle architecture
Diagramme en cours de génération...
2.3 États
- RN 0.74+ : nouvelle architecture activée par défaut (Android + iOS).
- La plupart des libs compatibles.
- RN 0.80 (2025) : le bridge legacy est supprimé/optionnel.
2.4 Pourquoi c'est mieux
- Temps de démarrage réduit (JSI, Hermes bytecode).
- Meilleure interaction JS↔natif (types, synchronie partielle).
- Meilleure performance de rendu (Fabric priorise la mise à jour).
- Support de
useSyncExternalStoreet des concurrent features de React.
3. Expo : managed workflow, EAS, dev clients
3.1 Qu'est-ce qu'Expo ?
Framework + écosystème au-dessus de React Native : outils, config, SDK, services cloud.
3.2 Workflows
| Workflow | Description |
|---|---|
| Managed (Expo Go) | Zéro config native, développement rapide, config via app.json |
| Development build | Build personnalisé avec modules natifs custom, via dev clients |
| Bare/Prebuild | Contrôle total des dossiers android/ et ios/ (générés par expo prebuild) |
3.3 Commencer
npx create-expo-app@latest mon-app
cd mon-app
npx expo start # QR code, Expo Go ou dev client
3.4 EAS (Expo Application Services)
- Build : builds cloud (Android AAB/APK, iOS IPA) sans machine macOS.
- Submit : soumission aux stores.
- Update : mises à jour OTA.
npm install -g eas-cli
eas build --platform android
eas submit
eas update --channel production
3.5 Dev clients
npx expo run:android # build local natif
npx expo-dev-client
Le dev client combine hot reload + accès aux modules natifs personnalisés.
3.6 Config plugins
Modifie la config native (Info.plist, AndroidManifest) via app.json :
{
"expo": {
"plugins": [
["expo-camera", { "cameraPermission": "Autoriser la caméra ?" }]
]
}
}
4. React Navigation
4.1 Fondations
React Navigation est la solution standard de navigation RN.
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
const Stack = createNativeStackNavigator<RootStackParamList>();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: true }}>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Detail" component={DetailScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
4.2 Types
export type RootStackParamList = {
Home: undefined;
Detail: { productId: number };
};
Typage du navigation prop :
type Props = NativeStackScreenProps<RootStackParamList, "Detail">;
4.3 Les navigateurs
createNativeStackNavigator: natif (meilleures perfs, gestures iOS).createBottomTabNavigator: tab bars.createDrawerNavigator: drawer.@react-navigation/material-top-tabs: tabs haut.
4.4 Patterns
- Paramètres :
navigation.navigate("Detail", { productId: 42 }). - Back :
navigation.goBack(). - Deep links via config :
const linking = {
prefixes: ["myapp://", "https://example.com"],
config: { screens: { Home: "", Detail: "product/:productId" } },
};
5. Styling : StyleSheet, NativeWind, styled-components
5.1 StyleSheet
import { StyleSheet, View, Text } from "react-native";
const styles = StyleSheet.create({
card: {
backgroundColor: "#fff",
borderRadius: 12,
padding: 16,
gap: 8,
},
title: { fontSize: 16, fontWeight: "600" },
});
<View style={styles.card}>
<Text style={styles.title}>Bonjour</Text>
</View>;
- Flexbox par défaut, unités en points (pas de px).
gapsupporté.
5.2 NativeWind
Tailwind CSS pour RN (v4+ : className natif).
<View className="bg-white rounded-2xl p-4 gap-2">
<Text className="text-base font-semibold text-slate-900">Bonjour</Text>
</View>
5.3 styled-components
import styled from "styled-components/native";
const Card = styled.View`
background: white;
border-radius: 12px;
padding: 16px;
`;
const Title = styled.Text`
font-size: 16px;
font-weight: 600;
`;
5.4 Choix
| Solution | Approche | Pour qui |
|---|---|---|
| StyleSheet | Native, statique | Le plus simple |
| NativeWind | Utility-first | Équipes Tailwind |
| styled-components | CSS-in-JS dynamique | Thèmes dynamiques |
6. Reanimated et gestures
6.1 Reanimated
Animations exécutées sur le thread UI natif (worklets), 60/120 fps.
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from "react-native-reanimated";
function LikeButton() {
const scale = useSharedValue(1);
const style = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
return (
<Animated.View style={style}>
<Pressable
onPress={() => (scale.value = withSpring(scale.value === 1 ? 1.3 : 1))}
>
<Text>❤️</Text>
</Pressable>
</Animated.View>
);
}
6.2 Worklets
Les fonctions marquées 'worklet' s'exécutent sur le thread UI.
const handleGesture = useAnimatedGestureHandler({
onStart: () => { "worklet"; },
onActive: (event) => { translation.value = event.translationX; },
});
6.3 React Native Gesture Handler
Gestes natifs (pan, tap, pinch, rotation, fling).
import { Gesture, GestureDetector } from "react-native-gesture-handler";
const pan = Gesture.Pan()
.onUpdate((e) => { translation.value = e.translationX; })
.onEnd(() => { translation.value = withSpring(0); });
<GestureDetector gesture={pan}>
<Animated.View style={style} />
</GestureDetector>;
6.4 Bonnes pratiques
- Animations UI → Reanimated (pas de
Animatedlegacy pour les cas intenses). - Gestes → Gesture Handler.
- Les transitions de navigation natifs : laisser le navigateur les gérer.
7. State management : Zustand, Redux Toolkit, React Query
7.1 Catégories d'état
- État serveur : données API → React Query / TanStack Query.
- État global client : thème, panier, session → Zustand, Redux Toolkit, Context.
- État local : useState/useReducer.
7.2 Zustand
Léger, simple, basé sur hooks.
import { create } from "zustand";
interface CartState {
items: CartItem[];
add: (item: CartItem) => void;
remove: (id: number) => void;
}
export const useCart = create<CartState>((set) => ({
items: [],
add: (item) => set((s) => ({ items: [...s.items, item] })),
remove: (id) => set((s) => ({ items: s.items.filter((i) => i.id !== id) })),
}));
// usage
const items = useCart((s) => s.items);
const add = useCart((s) => s.add);
7.3 Redux Toolkit
Standard structuré (slices, thunks, RTK Query).
import { createSlice } from "@reduxjs/toolkit";
const cartSlice = createSlice({
name: "cart",
initialState: { items: [] as CartItem[] },
reducers: {
add(state, action) { state.items.push(action.payload); },
remove(state, action) { state.items = state.items.filter((i) => i.id !== action.payload); },
},
});
7.4 React Query (TanStack Query)
Gère le cache serveur : fetch, retry, invalidation, refetch.
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
function useProducts() {
return useQuery({
queryKey: ["products"],
queryFn: () => api.getProducts(),
});
}
function useAddToCart() {
const qc = useQueryClient();
return useMutation({
mutationFn: (item: CartItem) => api.add(item),
onSuccess: () => qc.invalidateQueries({ queryKey: ["cart"] }),
});
}
7.5 Recommandations
- Par défaut : React Query pour le serveur + Zustand pour le global + useState pour le local.
- Redux Toolkit : pour les grosses équipes/processus déjà en place.
- Éviter de mettre l'état serveur dans le state global.
8. OTA updates : CodePush, Expo Updates
8.1 Pourquoi OTA ?
Distribuer une correction sans passer par la review des stores. Limité au bundle JS (pas de code natif).
Diagramme en cours de génération...
8.2 Expo Updates
{
"expo": {
"updates": { "url": "https://u.expo.dev/...", "enabled": true },
"runtimeVersion": "1.0.0"
}
}
eas update --channel production
- runtimeVersion : change quand le code natif change → force une mise à jour store.
- Les updates ne remplacent jamais un build natif pour les changements natifs.
8.3 CodePush (Microsoft App Center)
appcenter codepush release-react -a owner/App -d Production
8.4 Précautions OTA
- Ne pas distribuer de changements qui exigent des permissions natives.
- Rollout progressif (channels production/beta).
- Monitoring : si l'update casse l'app, les users restent coincés → rollback rapide prévu.
- Health checks et
releaseVersioncohérents.
9. Performance
9.1 Mesurer
- Metro :
npx react-native startavec bundle stats. - React DevTools → Profiler.
- Flipper (légacy) / modern debugging (Hermes CDP).
- Profiler natif (Xcode Instruments, Android Studio CPU).
- Expo :
npx expo start --profiler.
9.2 Les leviers
| Levier | Action |
|---|---|
| Moteur | Hermes activé |
| Rendu | Nouvelle architecture (Fabric) |
| Listes | FlatList avec getItemLayout, initialNumToRender, windowSize |
| Images | resizeMode, dimensions natives, cache (expo-image) |
| Re-renders | memo, useCallback, clés stables, sélecteurs Zustand |
| Thread UI | Reanimated pour les animations |
| Bundle | Metro : import lazy, new Arch, trim des modules |
| Hermes bytecode | Précompilation du bundle |
9.3 FlatList optimisé
<FlatList
data={products}
keyExtractor={(item) => String(item.id)}
renderItem={({ item }) => <MemoProductRow product={item} />}
initialNumToRender={10}
windowSize={7}
maxToRenderPerBatch={10}
updateCellsBatchingPeriod={50}
getItemLayout={(_, index) => ({ length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index })}
/>
9.4 Startup time
- Réduire le travail dans
index.js(lazy import des écrans). - Éviter les modules natifs lourds au démarrage (TurboModules paresseux).
- Splash screen minimal puis lazy hydrate.
10. Résumé et checklist
10.1 Points clés
- Architecture : JS thread + UI natif ; Hermes ; JSI.
- Nouvelle architecture : TurboModules, Fabric, codegen — par défaut.
- Expo : managed/prebuild, EAS build/submit/update, dev clients.
- React Navigation : stack/tabs/drawer typés, deep links.
- Styling : StyleSheet natif, NativeWind, styled-components.
- Reanimated (worklets) + Gesture Handler : 60/120 fps.
- State : React Query (serveur) + Zustand (global) + useState (local).
- OTA : Expo Updates / CodePush, runtimeVersion, rollout.
- Performance : Hermes, Fabric, FlatList, memo, Reanimated.
10.2 Checklist
- J'explique le bridge vs TurboModules/Fabric
- J'active Hermes et la nouvelle architecture
- Je crée un projet Expo et un dev client
- Je navigue avec des routes typées
- Je stylise avec StyleSheet ou NativeWind
- J'anime avec Reanimated et un geste
- Je gère l'état serveur (React Query) et global (Zustand)
- Je publie une mise à jour OTA
- J'optimise une FlatList
Prochain chapitre
→ 09-Flutter : Dart, widgets, state management, layout, navigation, animations, performance, tests, build.