Cours React Native Complet 📱
Les 12 chapitres essentiels — Expo, composants natifs, navigation, API et publication
🏠 Hub Programmation
⚡ JavaScript (prérequis)
⚛️ React (prérequis)
🔷 TypeScript
💙 Flutter
Introduction et installation
npx create-expo-app@latest mon-app
cd mon-app
# Lancer
npx expo start
# Tester :
# → Scanner le QR code avec Expo Go (téléphone)
# → Appuyer sur 'i' pour iOS simulator
# → Appuyer sur 'a' pour Android emulator
# → Appuyer sur 'w' pour le web
import from 'react-native';
export default function HomeScreen()
const styles = StyleSheet.create();
React Native est un framework de Meta pour créer des apps natives iOS et Android avec React et JavaScript/TypeScript. Contrairement à Flutter, il utilise les vrais composants natifs de chaque plateforme. Utilisé par Meta, Microsoft, Shopify, Discord et Coinbase. Expo est le framework recommandé pour démarrer.
| React Web | React Native |
|---|---|
| , | |
|
|
|
| CSS / className | StyleSheet / style= |
| Flexbox (row défaut) | Flexbox (column défaut) |
Composants de base
// Text — tout texte doit être dans
Titre
// Image
source=
style=
/>
// Pressable — bouton custom (remplace TouchableOpacity)
onPress=
style=
>
// ScrollView — contenu scrollable
// ActivityIndicator — spinner de chargement
Tout texte doit être dans
StyleSheet et layout
const styles = StyleSheet.create();
// Row — aligner horizontalement
// flex: 1 = prendre tout l'espace restant
// gap (React Native 0.71+)
Flexbox en React Native est en column par défaut (vertical), contrairement au web (row). justifyContent agit sur l'axe principal (vertical), alignItems sur l'axe secondaire (horizontal). Toutes les dimensions sont en dp (density-independent pixels), pas en px.
State et hooks
export default function Counter()
Les hooks sont 100% identiques à React web. useState, useEffect, useCallback, useMemo, useRef, useContext — tout fonctionne pareil. La seule différence est le rendu : des composants natifs au lieu du HTML.
Listes
data=
keyExtractor=
renderItem=
ItemSeparatorComponent=
ListEmptyComponent=
refreshing=
onRefresh= // Pull to refresh
onEndReached= // Pagination infinie
onEndReachedThreshold=
/>
// SectionList — liste avec sections (headers)
import from 'react-native';
sections=
renderSectionHeader=
renderItem=
/>
Ne jamais utiliser ScrollView + map() pour de longues listes. FlatList est virtualisé — il ne rend que les items visibles à l'écran. ScrollView rend TOUS les items en mémoire, ce qui cause des problèmes de performance avec > 50 items.
Navigation
// Structure des fichiers = routes
//
// app/
// _layout.tsx → Layout racine
// index.tsx → Route « / »
// (tabs)/
// _layout.tsx → Tab bar layout
// index.tsx → Tab « Accueil »
// search.tsx → Tab « Chercher »
// profile.tsx → Tab « Profil »
// post/
// [id].tsx → Route dynamique /post/42
import from 'expo-router';
import from '@expo/vector-icons';
export default function TabLayout()
import from 'expo-router';
// Push
router.push('/post/42');
router.push();
// Remplacer
router.replace('/login');
// Retour
router.back();
// Lire les params (dans post/[id].tsx)
const = useLocalSearchParams<>();
Formulaires
import from 'react-native';
export default function LoginForm() {
const [email, setEmail] = useState( »);
const [password, setPassword] = useState( »);
const handleSubmit = () => {
if (!email || !password) {
Alert.alert('Erreur', 'Remplissez tous les champs');
return;
}
// Envoyer…
};
return (
placeholder=« Email »
value={email}
onChangeText={setEmail}
keyboardType=« email-address »
autoCapitalize=« none »
style={styles.input}
/>
placeholder=« Mot de passe »
value={password}
onChangeText={setPassword}
secureTextEntry
style={styles.input}
/>
);
}
HTTP et API
async function fetchPosts()
// npm install @tanstack/react-query
import from '@tanstack/react-query';
export default function PostList() {
const { data: posts, isLoading, error } = useQuery({
queryKey: ['posts'],
queryFn: fetchPosts,
});
if (isLoading) return
if (error) return
return (
data=
keyExtractor=
renderItem={({ item }) =>
/>
);
}
// Mutation (POST, PUT, DELETE)
const queryClient = useQueryClient();
const mutation = useMutation();
State management
import from 'zustand';
// Créer un store
const useAuthStore = create((set) => ());
// Utiliser dans un composant
export default function Profile()
| Solution | Complexité | Idéal pour |
|---|---|---|
| useState + Context | Simple | Petit état partagé |
| Zustand | Simple | État global (recommandé) |
| TanStack Query | Moyen | État serveur (API, cache) |
| Redux Toolkit | Complexe | Apps enterprise, logique complexe |
Stockage et natif
import AsyncStorage from '@react-native-async-storage/async-storage';
// Sauvegarder
await AsyncStorage.setItem('token', 'abc123');
await AsyncStorage.setItem('user', JSON.stringify(user));
// Lire
const token = await AsyncStorage.getItem('token');
const user = JSON.parse(await AsyncStorage.getItem('user'));
// Supprimer
await AsyncStorage.removeItem('token');
// expo-secure-store — pour les données sensibles (tokens, passwords)
// npx expo install expo-secure-store
import * as SecureStore from 'expo-secure-store';
await SecureStore.setItemAsync('token', 'secret');
// npx expo install expo-camera expo-location expo-notifications
// Caméra
import from 'expo-camera';
// Géolocalisation
import * as Location from 'expo-location';
const = await Location.requestForegroundPermissionsAsync();
const loc = await Location.getCurrentPositionAsync();
// Notifications push
import * as Notifications from 'expo-notifications';
Publication
npm install -g eas-cli
eas login
# Configurer
eas build:configure
# Build pour les stores
eas build –platform android # → .aab pour Play Store
eas build –platform ios # → .ipa pour App Store
eas build –platform all # Les deux
# Soumettre aux stores
eas submit –platform android
eas submit –platform ios
# Update Over-The-Air (OTA) — sans repasser par les stores !
eas update –branch production –message « Fix bug »
EAS Update = mises à jour instantanées sans repasser par les stores. Les changements JS/assets sont envoyés directement aux utilisateurs. Seuls les changements de code natif (nouvelles permissions, nouveau SDK) nécessitent un nouveau build store.
| Étape | Outil |
|---|---|
| Icône et splash screen | app.json → icon, splash |
| Build production | eas build |
| Tests sur device réel | Expo Go / Development Build |
| Google Play Console | 25$ une fois |
| App Store Connect | 99$/an (Apple Developer) |
| OTA updates | eas update |
Bonnes pratiques
| Besoin | Outil |
|---|---|
| Framework | Expo (avec Expo Router) |
| Navigation | Expo Router (file-based) |
| State global | Zustand |
| State serveur | TanStack Query |
| Stockage | AsyncStorage + SecureStore |
| UI | NativeWind (Tailwind pour RN) ou Tamagui |
| Icônes | @expo/vector-icons |
| Animations | react-native-reanimated |
| Formulaires | react-hook-form + zod |
✅ À FAIRE
• FlatList pour les listes (virtualisé)
• Pressable au lieu de TouchableOpacity
• TypeScript
• Expo Router (file-based)
• TanStack Query pour les API
• Zustand pour l'état global
• Tester sur iOS ET Android
• expo-secure-store pour les tokens
• Animations avec Reanimated
❌ À ÉVITER
• ScrollView + map() pour les listes
• Inline styles partout (utiliser StyleSheet)
• Ignorer les différences iOS/Android
• console.log en production
• Images non optimisées
• Pas de gestion d'erreurs réseau
• State global dans Context (perf)
• Ignorer les permissions (caméra, GPS)
• Oublier de tester sur device réel
🏠 Hub Programmation
⚛️ Cours React
⚡ Cours JavaScript
🔷 Cours TypeScript
💙 Cours Flutter
🎨 Cours Tailwind CSS
Cours React Native Complet — Expo, composants natifs, navigation et publication
Référence : reactnative.dev | Expo | NativeWind

