Objectifs de cette leçon
- Effectuer des requêtes API avec fetch/axios
- Gérer les erreurs réseau
- Afficher des données depuis une API
Communication réseau et API 🌐
Une app mobile sans réseau, c'est comme un téléphone sans forfait ! React Native permet d'appeler des API, gérer l'authentification et même du temps réel.
1. fetch et axios — les appels API 🔌
' fetch = intégré à JavaScript (pas besoin d'installer) ' axios = bibliothèque externe (plus de fonctionnalités) ' HTTP (GET, POST, PUT, DELETE) = les verbes de la communication ' GET → lire des données ' POST → créer des données ' PUT → modifier des données ' DELETE → supprimer des données
tsx // Avec fetch (natif) interface Article { id: number; titre: string; contenu: string; auteur: string; }
async function chargerArticles(): Promise<Article[]> { const reponse = await fetch("https://api.exemple.com/articles", { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer token123", }, });
if (!reponse.ok) {
throw new Error(Erreur HTTP : ${reponse.status});
}
return reponse.json(); }
// Avec axios (plus concis) import axios from "axios";
const api = axios.create({ baseURL: "https://api.exemple.com", timeout: 10000, // 10 secondes max headers: { "Content-Type": "application/json" }, });
// Intercepteur : ajoute le token à TOUTES les requêtes
api.interceptors.request.use((config) => {
const token = "mon-jwt-token";
config.headers.Authorization = Bearer ${token};
return config;
});
// Utilisation const { data } = await api.get<Article[]>("/articles"); const nouveau = await api.post("/articles", { titre: "Mon article" }); ``'
2. Gestion des erreurs et loading ⚠️
import { useState } from "react"; import { View, Text, TouchableOpacity, ActivityIndicator, StyleSheet } from "react-native"; function ChargementDonnees() { const [donnees, setDonnees] = useState<Article[]>([]); const [loading, setLoading] = useState(false); const [erreur, setErreur] = useState<string | null>(null); const charger = async () => { setLoading(true); setErreur(null); try { const reponse = await fetch("https://api.exemple.com/articles"); if (!reponse.ok) { if (reponse.status === 401) throw new Error("Non autorisé"); if (reponse.status === 404) throw new Error("Pas trouvé"); throw new Error("Erreur serveur"); } const data = await reponse.json(); setDonnees(data); } catch (err) { if (err instanceof TypeError) { setErreur("Pas de connexion internet"); } else { setErreur(err.message); } } finally { setLoading(false); } }; return ( <View style={styles.container}> <TouchableOpacity onPress={charger} disabled={loading}> <Text>{loading ? "Chargement..." : "Charger"}</Text> </TouchableOpacity> {loading && <ActivityIndicator size="large" color="#6200ee" />} {erreur && ( <View style={styles.erreur}> <Text style={styles.erreurTexte}>❌ {erreur}</Text> <TouchableOpacity onPress={charger}> <Text style={styles.retry}>Réessayer</Text> </TouchableOpacity> </View> )} {donnees.map((article) => ( <Text key={article.id}>{article.titre}</Text> ))} </View> ); } ``' --- ## 3. Authentification JWT 🔐 ```text ' JWT (JSON Web Token) = un "pass" numérique ' 1. L'utilisateur se connecte (email + mot de passe) ' 2. Le serveur vérifie et renvoie un JWT ' 3. L'app stocke le JWT (dans un endroit sécurisé) ' 4. Chaque requête inclut le JWT dans l'en-tête ' 5. Le serveur vérifie le JWT avant de répondre ``' tsx // Stockage sécurisé du token import * as SecureStore from "expo-secure-store"; const TOKEN_KEY = "auth_token"; export async function sauvegarderToken(token: string) { await SecureStore.setItemAsync(TOKEN_KEY, token); } export async function getToken(): Promise<string | null> { return SecureStore.getItemAsync(TOKEN_KEY); } export async function supprimerToken() { await SecureStore.deleteItemAsync(TOKEN_KEY); } // Connexion async function connexion(email: string, motDePasse: string) { const reponse = await fetch("https://api.exemple.com/login", { method: "POST", body: JSON.stringify({ email, motDePasse }), }); if (!reponse.ok) throw new Error("Email ou mot de passe incorrect"); const { token } = await reponse.json(); await sauvegarderToken(token); } ``' --- ## 4. WebSockets — temps réel ⚡ ```tsx import { useEffect, useState } from "react"; import { Text, View } from "react-native"; function ChatTempsReel() { const [messages, setMessages] = useState<string[]>([]); const [socket, setSocket] = useState<WebSocket | null>(null); useEffect(() => { // Connexion WebSocket const ws = new WebSocket("wss://chat.exemple.com"); ws.onopen = () => console.log("Connecté au chat"); ws.onmessage = (event) => { setMessages((prev) => [...prev, event.data]); }; ws.onclose = () => console.log("Déconnecté"); ws.onerror = (err) => console.error("Erreur WS", err); setSocket(ws); // Nettoyage return () => ws.close(); }, []); const envoyerMessage = (texte: string) => { socket?.send(JSON.stringify({ type: "message", texte })); }; return ( <View> {messages.map((msg, i) => ( <Text key={i}>{msg}</Text> ))} </View> ); } ``' --- ## 5. Bonnes pratiques ✅ ```text ' 1. TOUJOURS gérer les erreurs (try/catch) ' 2. Afficher un indicateur de chargement ' 3. Timeout sur chaque requête (max 10-15 sec) ' 4. Retry automatique si échec (3 tentatives max) ' 5. Cache les réponses pour éviter de recharger ' 6. Stocker les tokens dans un endroit SÉCURISÉ ' 7. Ne JAMAIS mettre les clés API en dur dans le code ``' --- ## Exercices pour toi 🎯 1. **GET + liste** : utilise l'API JSONPlaceholder (`/posts`) pour afficher une liste de posts avec FlatList, loading et gestion d'erreur 2. **POST + formulaire** : crée un formulaire d'inscription qui envoie email + password à une API et gère la réponse (succès/erreur) 3. **JWT complet** : implémente login → stockage du token → requête authentifiée → déconnexion
Création des variables pas à pas
Prêt à explorer la mémoire
Appuie sur Play pour voir les variables se créer une par une
Visualisation d'exécution
ligne 14🌐 Cycle de vie d'un appel API
⚡ Simulateur — Communication réseau
Étape 1/8React Native utilise fetch() comme sur le web pour communiquer avec des API.