Intégration d'APIs et Requêtes Réseau dans React Native
Bienvenue dans cette leçon fondamentale sur l'intégration d'APIs (Application Programming Interfaces) et la gestion des requêtes réseau dans vos applications React Native. Dans le monde du développement mobile, rares sont les applications qui fonctionnent de manière isolée. La plupart interagissent avec des services externes pour récupérer, envoyer ou synchroniser des données. Comprendre comment interagir avec ces services est donc une compétence indispensable.
Introduction : Le Cœur des Applications Connectées
Les applications mobiles modernes ne sont plus de simples outils autonomes. Elles sont des portails vers une multitude de services, de contenus dynamiques et d'interactions utilisateur riches. C'est là que les APIs entrent en jeu.
Qu'est-ce qu'une API ?
Une API est un ensemble de règles et de définitions qui permet à différentes applications logicielles de communiquer entre elles. Imaginez une API comme le menu d'un restaurant : il liste ce que vous pouvez commander (les requêtes) et ce que vous pouvez attendre en retour (les réponses), sans avoir à savoir comment le plat est préparé en cuisine.
Pour une application mobile, une API est généralement une interface web qui permet :
- De récupérer des données (ex: liste de produits, articles de blog, données météo).
- D'envoyer des données (ex: créer un nouveau compte utilisateur, poster un commentaire, soumettre un formulaire).
- De modifier des données existantes (ex: mettre à jour un profil utilisateur).
- De supprimer des données.
Pourquoi l'intégration d'APIs est-elle cruciale pour les applications mobiles ?
- Contenu Dynamique : Afficher des informations qui évoluent constamment (actualités, cours de bourse, posts de réseaux sociaux).
- Fonctionnalités Étendues : Intégrer des services tiers (paiement en ligne, cartes géographiques, authentification via Google/Facebook).
- Persistance des Données : Sauvegarder les données utilisateurs ou d'application sur un serveur pour qu'elles soient accessibles depuis n'importe quel appareil.
- Collaboration et Synchronisation : Permettre à plusieurs utilisateurs d'interagir avec les mêmes données ou de synchroniser des informations entre différentes plateformes.
Dans cette leçon, nous allons explorer les concepts clés des requêtes réseau, les outils disponibles dans React Native pour les gérer, et les bonnes pratiques pour construire des applications robustes et performantes.
Comprendre les Fondamentaux des APIs et Requêtes Réseau
Avant de plonger dans le code React Native, il est essentiel de maîtriser les concepts sous-jacents aux interactions avec les APIs web.
Qu'est-ce qu'une API RESTful ?
La majorité des APIs web modernes que vous rencontrerez sont basées sur le style architectural REST (Representational State Transfer). Une API RESTful adhère à plusieurs principes, dont les plus importants sont :
- Ressources : Tout est une ressource (un utilisateur, un produit, une commande). Chaque ressource est identifiée par une URL unique (Uniform Resource Locator).
- Ex:
https://api.monservice.com/utilisateurs - Ex:
https://api.monservice.com/produits/123
- Ex:
- Verbes HTTP : Les opérations sur ces ressources sont définies par les verbes HTTP.
- Communication sans État (Stateless) : Chaque requête du client au serveur contient toutes les informations nécessaires pour que le serveur puisse comprendre et traiter la requête. Le serveur ne conserve aucune information sur les requêtes précédentes du client.
Verbes HTTP Courants
Les verbes HTTP, également appelés méthodes HTTP, indiquent le type d'action que le client souhaite effectuer sur la ressource identifiée par l'URL.
GET: Récupérer des données. C'est le verbe le plus courant. Il est utilisé pour demander des données à une ressource spécifique ou à une collection de ressources.- Ex:
GET /produits(récupérer tous les produits) - Ex:
GET /produits/123(récupérer le produit avec l'ID 123)
- Ex:
POST: Créer une nouvelle ressource. Les données à créer sont envoyées dans le corps de la requête.- Ex:
POST /produits(créer un nouveau produit)
- Ex:
PUT: Mettre à jour une ressource existante, ou la créer si elle n'existe pas. Il remplace généralement la ressource complète.- Ex:
PUT /produits/123(remplacer les données du produit 123)
- Ex:
DELETE: Supprimer une ressource.- Ex:
DELETE /produits/123(supprimer le produit 123)
- Ex:
PATCH: Mettre à jour partiellement une ressource existante. (Moins fréquent quePUTmais utile pour de petites modifications).
Format d'Échange de Données : JSON (JavaScript Object Notation)
Lors de l'échange de données avec une API, un format standard est nécessaire pour que le client et le serveur puissent se comprendre. Le format le plus répandu aujourd'hui est JSON.
- Léger et Lisible : JSON est un format de texte léger et facilement lisible par les humains et les machines.
- Basé sur JavaScript : Sa syntaxe est directement dérivée de la notation d'objets JavaScript, ce qui le rend très naturel à manipuler dans un environnement JavaScript comme React Native.
- Représentation des Données : Il permet de représenter des objets, des tableaux, des chaînes de caractères, des nombres, des booléens et des valeurs nulles.
Exemple de données JSON :
{
"id": 1,
"titre": "Apprendre React Native",
"auteur": {
"nom": "Jane Doe",
"email": "jane.doe@example.com"
},
"tags": ["mobile", "javascript", "react-native"],
"estPublie": true
}
Lorsque vous envoyez des données (POST, PUT, PATCH), vous les "sérialisez" en JSON (convertissez un objet JavaScript en chaîne JSON). Lorsque vous recevez des données, vous les "désérialisez" (convertissez une chaîne JSON en objet JavaScript).
Requêtes Asynchrones : Promesses et async/await
Les requêtes réseau prennent du temps. Elles dépendent de la vitesse de votre connexion Internet, de la latence du serveur et de la complexité de l'opération. Si ces requêtes étaient "synchrones" (bloquantes), votre application se figerait complètement pendant l'attente de la réponse du serveur, ce qui est une très mauvaise expérience utilisateur.
C'est pourquoi les requêtes réseau sont asynchrones et non bloquantes. Cela signifie que votre application continue de fonctionner pendant que la requête est en cours en arrière-plan. Une fois la réponse reçue, un "callback" ou une "promesse" est exécutée pour traiter les données.
En JavaScript moderne, la gestion de l'asynchronisme repose principalement sur les Promesses et la syntaxe async/await.
-
Promesse : Un objet qui représente l'achèvement (ou l'échec) éventuel d'une opération asynchrone et sa valeur résultante.
- Une promesse peut être dans l'un des trois états :
pending(en attente) : état initial, ni réalisée ni rejetée.fulfilled(réalisée) : l'opération a réussi, la promesse a une valeur.rejected(rejetée) : l'opération a échoué, la promesse a une raison (erreur).
- Vous utilisez
.then()pour gérer le succès et.catch()pour gérer l'échec.
- Une promesse peut être dans l'un des trois états :
-
async/await: Une syntaxe plus propre et plus facile à lire pour travailler avec les promesses.- Le mot-clé
asyncdevant une fonction indique que cette fonction retourne implicitement une promesse. - Le mot-clé
awaitpeut être utilisé uniquement à l'intérieur d'une fonctionasync. Il "met en pause" l'exécution de la fonctionasyncjusqu'à ce que la promesseawaitée soit résolue (réussie ou échouée), puis reprend l'exécution avec la valeur résolue.
- Le mot-clé
C'est la méthode privilégiée pour gérer les requêtes réseau dans React Native.
Intégration d'APIs dans React Native
React Native offre plusieurs façons d'effectuer des requêtes réseau. Les deux plus courantes sont l'API fetch native et la bibliothèque tierce Axios.
L'API fetch native
L'API fetch est une API web standard, disponible nativement dans React Native (et dans la plupart des navigateurs modernes). Elle fournit une interface générique pour effectuer des requêtes réseau. C'est l'option par défaut si vous n'avez pas besoin de fonctionnalités avancées.
Points clés de fetch :
- Basé sur les Promesses : Toutes les opérations
fetchretournent des promesses. - Simple : Très simple pour les requêtes GET basiques.
- Gestion manuelle de JSON et des erreurs : Vous devez explicitement appeler
.json()pour parser la réponse et vérifierresponse.okpour détecter les erreurs HTTP.
Exemple de Requête GET avec fetch
Récupérons une liste d'articles depuis une API de test publique (jsonplaceholder.typicode.com).
import React, { useState, useEffect } from 'react';
import { View, Text, FlatList, ActivityIndicator, StyleSheet, Alert } from 'react-native';
const ArticlesScreen = () => {
const [articles, setArticles] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchArticles = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
// Vérifier si la réponse est un succès (statut 2xx)
if (!response.ok) {
// Si non, lancer une erreur avec le statut
throw new Error(`HTTP error! status: ${response.status}`);
}
// Parser la réponse JSON
const data = await response.json();
setArticles(data);
} catch (e) {
console.error("Erreur lors de la récupération des articles:", e);
setError(e.message); // Stocker le message d'erreur
Alert.alert("Erreur", "Impossible de charger les articles. Veuillez réessayer.");
} finally {
setLoading(false); // Arrêter l'indicateur de chargement
}
};
fetchArticles();
}, []); // Le tableau vide [] signifie que ce useEffect ne s'exécute qu'une fois, au montage du composant
if (loading) {
return (
<View style={styles.center}>
<ActivityIndicator size="large" color="#0000ff" />
<Text>Chargement des articles...</Text>
</View>
);
}
if (error) {
return (
<View style={styles.center}>
<Text style={styles.errorText}>Erreur: {error}</Text>
<Text>Vérifiez votre connexion internet ou réessayez plus tard.</Text>
</View>
);
}
return (
<View style={styles.container}>
<Text style={styles.title}>Liste des Articles</Text>
<FlatList
data={articles}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => (
<View style={styles.articleItem}>
<Text style={styles.articleTitle}>{item.title}</Text>
<Text style={styles.articleBody}>{item.body.substring(0, 100)}...</Text>
</View>
)}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 50,
paddingHorizontal: 20,
backgroundColor: '#f5f5f5',
},
center: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
title: {
fontSize: 28,
fontWeight: 'bold',
marginBottom: 20,
textAlign: 'center',
color: '#333',
},
articleItem: {
backgroundColor: '#fff',
padding: 15,
borderRadius: 8,
marginBottom: 10,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.2,
shadowRadius: 1.41,
elevation: 2,
},
articleTitle: {
fontSize: 18,
fontWeight: '600',
color: '#007bff',
marginBottom: 5,
},
articleBody: {
fontSize: 14,
color: '#555',
lineHeight: 20,
},
errorText: {
color: 'red',
fontSize: 16,
textAlign: 'center',
marginBottom: 10,
},
});
export default ArticlesScreen;
Explication du code :
useStateHooks : Nous utilisonsuseStatepour gérer trois états :articles(pour stocker les données reçues),loading(pour indiquer si la requête est en cours), eterror(pour stocker un message d'erreur si la requête échoue).useEffectHook : Ce hook est utilisé pour déclencher la requête API une fois que le composant est monté. Le tableau de dépendances vide[]garantit qu'il ne s'exécutera qu'une seule fois.- Fonction
fetchArticles:- Elle est déclarée comme
asyncpour pouvoir utiliserawait. setLoading(true): Met l'état de chargement à vrai avant la requête.await fetch(...): Exécute la requête GET. Par défaut,fetchfait une requête GET si le paramètremethodn'est pas spécifié.if (!response.ok): Très important !fetchne rejette une promesse qu'en cas d'erreur réseau (ex: pas de connexion). Pour les erreurs HTTP (comme 404 Not Found, 500 Internal Server Error),response.okserafalse. Nous devons donc vérifier cela manuellement etthrow new Error()pour que le bloccatchle gère.await response.json(): Parse la chaîne de caractères JSON reçue en un objet JavaScript utilisable. Ceci est également une opération asynchrone.setArticles(data): Met à jour l'étatarticlesavec les données reçues.try...catch...finally: Structure standard pour gérer l'asynchronisme et les erreurs.catchattrape les erreurs réseau ou celles que nous avons levées manuellement.finallys'exécute toujours, que la requête réussisse ou échoue, idéal pour mettresetLoading(false).
- Elle est déclarée comme
- Affichage Conditionnel : Nous affichons un
ActivityIndicatorpendant le chargement, un message d'erreur sierrorest défini, ou la liste des articles (FlatList) une fois les données chargées.
Exemple de Requête POST avec fetch
Pour envoyer des données, vous devez configurer la méthode (POST), les en-têtes (notamment Content-Type: application/json) et le corps de la requête (les données JSON stringifiées).
import React, { useState } from 'react';
import { View, Text, TextInput, Button, StyleSheet, ActivityIndicator, Alert } from 'react-native';
const CreateArticleScreen = () => {
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
const [loading, setLoading] = useState(false);
const handleCreateArticle = async () => {
if (!title || !body) {
Alert.alert("Erreur", "Veuillez remplir tous les champs.");
return;
}
setLoading(true);
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST', // Spécifier la méthode POST
headers: {
'Content-Type': 'application/json', // Indiquer que le corps est du JSON
},
body: JSON.stringify({ // Convertir l'objet JS en chaîne JSON
title: title,
body: body,
userId: 1, // Un userId est souvent requis par l'API
}),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const newArticle = await response.json();
console.log('Article créé avec succès:', newArticle);
Alert.alert("Succès", `Article "${newArticle.title}" créé avec l'ID: ${newArticle.id}`);
setTitle(''); // Réinitialiser les champs
setBody('');
} catch (e) {
console.error("Erreur lors de la création de l'article:", e);
Alert.alert("Erreur", `Impossible de créer l'article: ${e.message}`);
} finally {
setLoading(false);
}
};
return (
<View style={styles.container}>
<Text style={styles.title}>Créer un Nouvel Article</Text>
<TextInput
style={styles.input}
placeholder="Titre de l'article"
value={title}
onChangeText={setTitle}
/>
<TextInput
style={styles.textArea}
placeholder="Contenu de l'article"
value={body}
onChangeText={setBody}
multiline
numberOfLines={4}
/>
<Button
title={loading ? "Création en cours..." : "Créer l'article"}
onPress={handleCreateArticle}
disabled={loading}
/>
{loading && <ActivityIndicator size="small" color="#0000ff" style={styles.indicator} />}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
justifyContent: 'center',
backgroundColor: '#f5f5f5',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 30,
textAlign: 'center',
color: '#333',
},
input: {
height: 50,
borderColor: '#ddd',
borderWidth: 1,
borderRadius: 8,
paddingHorizontal: 15,
marginBottom: 15,
backgroundColor: '#fff',
fontSize: 16,
},
textArea: {
height: 120,
borderColor: '#ddd',
borderWidth: 1,
borderRadius: 8,
paddingHorizontal: 15,
paddingTop: 15, // Pour que le texte ne commence pas tout en haut
marginBottom: 20,
backgroundColor: '#fff',
fontSize: 16,
textAlignVertical: 'top', // Pour Android, aligne le texte en haut
},
indicator: {
marginTop: 15,
},
});
export default CreateArticleScreen;
Explication du code :
- Le second argument de
fetchest un objet de configuration. method: 'POST': Définit la méthode HTTP.headers: { 'Content-Type': 'application/json' }: Indique au serveur que le corps de la requête est au format JSON. C'est crucial pour que le serveur puisse parser correctement les données.body: JSON.stringify(...): Convertit l'objet JavaScript contenant les données du nouvel article en une chaîne JSON avant de l'envoyer.
Axios : Une Alternative Populaire
Bien que fetch soit parfaitement fonctionnel, beaucoup de développeurs préfèrent utiliser des bibliothèques tierces comme Axios en raison de ses fonctionnalités supplémentaires et de son ergonomie améliorée.
Pourquoi utiliser Axios ?
- Gestion automatique de JSON : Axios parse automatiquement les réponses JSON et
stringifieles corps de requêtes JSON. Pas besoin deresponse.json()ni deJSON.stringify(). - Meilleure gestion des erreurs : Axios rejette automatiquement les promesses pour les statuts HTTP 4xx/5xx (contrairement à
fetch), simplifiant la logiquetry/catch. - Intercepteurs : Vous pouvez intercepter les requêtes ou les réponses avant qu'elles ne soient envoyées ou traitées. Très utile pour ajouter des en-têtes d'authentification, gérer les erreurs globales, etc.
- Annulation de requêtes : Permet d'annuler des requêtes en cours (utile si un composant est démonté avant la fin de la requête).
- Barre de progression de téléchargement/upload.
- Support des requêtes côté serveur (Node.js) et côté client.
Installation d'Axios
Axios n'est pas natif, vous devez l'installer :
npm install axios
# ou
yarn add axios
Exemple de Requête GET avec Axios
import React, { useState, useEffect } from 'react';
import { View, Text, FlatList, ActivityIndicator, StyleSheet, Alert } from 'react-native';
import axios from 'axios'; // Importer Axios
const ArticlesAxiosScreen = () => {
const [articles, setArticles] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchArticles = async () => {
try {
// Axios parse automatiquement le JSON et rejette pour les erreurs HTTP
const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
setArticles(response.data); // Les données sont directement dans response.data
} catch (e) {
console.error("Erreur lors de la récupération des articles (Axios):", e);
// Axios fournit plus de détails sur l'erreur
if (e.response) {
// La requête a été faite et le serveur a répondu avec un statut en dehors de la plage 2xx
setError(`Erreur Serveur: ${e.response.status} - ${e.response.data.message || 'Unknown error'}`);
} else if (e.request) {
// La requête a été faite mais aucune réponse n'a été reçue (ex: réseau indisponible)
setError("Pas de réponse du serveur. Vérifiez votre connexion.");
} else {
// Quelque chose d'autre s'est mal passé lors de la configuration de la requête
setError(`Erreur: ${e.message}`);
}
Alert.alert("Erreur", "Impossible de charger les articles. Veuillez réessayer.");
} finally {
setLoading(false);
}
};
fetchArticles();
}, []);
if (loading) {
return (
<View style={styles.center}>
<ActivityIndicator size="large" color="#0000ff" />
<Text>Chargement des articles (Axios)...</Text>
</View>
);
}
if (error) {
return (
<View style={styles.center}>
<Text style={styles.errorText}>Erreur: {error}</Text>
<Text>Vérifiez votre connexion internet ou réessayez plus tard.</Text>
</View>
);
}
return (
<View style={styles.container}>
<Text style={styles.title}>Liste des Articles (Axios)</Text>
<FlatList
data={articles}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => (
<View style={styles.articleItem}>
<Text style={styles.articleTitle}>{item.title}</Text>
<Text style={styles.articleBody}>{item.body.substring(0, 100)}...</Text>
</View>
)}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 50,
paddingHorizontal: 20,
backgroundColor: '#f5f5f5',
},
center: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
title: {
fontSize: 28,
fontWeight: 'bold',
marginBottom: 20,
textAlign: 'center',
color: '#333',
},
articleItem: {
backgroundColor: '#fff',
padding: 15,
borderRadius: 8,
marginBottom: 10,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.2,
shadowRadius: 1.41,
elevation: 2,
},
articleTitle: {
fontSize: 18,
fontWeight: '600',
color: '#007bff',
marginBottom: 5,
},
articleBody: {
fontSize: 14,
color: '#555',
lineHeight: 20,
},
errorText: {
color: 'red',
fontSize: 16,
textAlign: 'center',
marginBottom: 10,
},
});
export default ArticlesAxiosScreen;
Explication du code :
import axios from 'axios';: Importe la bibliothèque.await axios.get(...): Exécute une requête GET. Axios fournit des méthodes raccourcies pour chaque verbe HTTP (axios.post,axios.put, etc.).response.data: Axios enveloppe la réponse HTTP et place les données JSON directement dans la propriétédata. Pas besoin deresponse.json().- Gestion des erreurs : C'est là qu'Axios brille. Si le statut HTTP n'est pas dans la plage 2xx, la promesse est automatiquement rejetée. L'objet
edans le bloccatchest un objetAxiosErrorqui contient des propriétés utiles commee.response(pour les erreurs du serveur),e.request(pour les erreurs réseau) oue.message(pour d'autres erreurs).
Exemple de Requête POST avec Axios
import React, { useState } from 'react';
import { View, Text, TextInput, Button, StyleSheet, ActivityIndicator, Alert } from 'react-native';
import axios from 'axios';
const CreateArticleAxiosScreen = () => {
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
const [loading, setLoading] = useState(false);
const handleCreateArticle = async () => {
if (!title || !body) {
Alert.alert("Erreur", "Veuillez remplir tous les champs.");
return;
}
setLoading(true);
try {
// Axios prend directement l'objet JS comme corps de requête
// et gère automatiquement l'en-tête Content-Type et JSON.stringify
const response = await axios.post('https://jsonplaceholder.typicode.com/posts', {
title: title,
body: body,
userId: 1,
});
const newArticle = response.data; // Les données de la réponse sont dans .data
console.log('Article créé avec succès (Axios):', newArticle);
Alert.alert("Succès", `Article "${newArticle.title}" créé avec l'ID: ${newArticle.id}`);
setTitle('');
setBody('');
} catch (e) {
console.error("Erreur lors de la création de l'article (Axios):", e);
if (e.response) {
Alert.alert("Erreur", `Impossible de créer l'article: ${e.response.status} - ${e.response.data.message || 'Erreur serveur'}`);
} else {
Alert.alert("Erreur", `Impossible de créer l'article: ${e.message}`);
}
} finally {
setLoading(false);
}
};
return (
<View style={styles.container}>
<Text style={styles.title}>Créer un Nouvel Article (Axios)</Text>
<TextInput
style={styles.input}
placeholder="Titre de l'article"
value={title}
onChangeText={setTitle}
/>
<TextInput
style={styles.textArea}
placeholder="Contenu de l'article"
value={body}
onChangeText={setBody}
multiline
numberOfLines={4}
/>
<Button
title={loading ? "Création en cours..." : "Créer l'article"}
onPress={handleCreateArticle}
disabled={loading}
/>
{loading && <ActivityIndicator size="small" color="#0000ff" style={styles.indicator} />}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
justifyContent: 'center',
backgroundColor: '#f5f5f5',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 30,
textAlign: 'center',
color: '#333',
},
input: {
height: 50,
borderColor: '#ddd',
borderWidth: 1,
borderRadius: 8,
paddingHorizontal: 15,
marginBottom: 15,
backgroundColor: '#fff',
fontSize: 16,
},
textArea: {
height: 120,
borderColor: '#ddd',
borderWidth: 1,
borderRadius: 8,
paddingHorizontal: 15,
paddingTop: 15,
marginBottom: 20,
backgroundColor: '#fff',
fontSize: 16,
textAlignVertical: 'top',
},
indicator: {
marginTop: 15,
},
});
export default CreateArticleAxiosScreen;
Explication du code :
await axios.post('URL', { ...data }): Le deuxième argument deaxios.postest l'objet JavaScript contenant les données à envoyer. Axios s'occupe de lestringifieren JSON et de définir l'en-têteContent-Typeapproprié. C'est beaucoup plus concis qu'avecfetch.
En résumé sur fetch vs Axios :
fetch: Natif, plus léger, parfait pour les requêtes simples si vous êtes à l'aise avec la gestion manuelle du JSON et des erreurs.- Axios : Nécessite une installation, offre une meilleure ergonomie, une gestion d'erreur plus intuitive et des fonctionnalités avancées comme les intercepteurs. Pour la plupart des applications complexes, Axios est souvent préféré.
Gestion des États et Affichage des Données
Comme illustré dans les exemples, l'intégration d'APIs va de pair avec la gestion d'état de votre composant.
useState: Permet de stocker les données récupérées (articles), l'état de chargement (loading), et les messages d'erreur (error). Ces états sont utilisés pour rendre l'interface utilisateur dynamique.useEffect: Est le hook idéal pour déclencher des effets secondaires comme les requêtes réseau. Lorsqu'il est utilisé avec un tableau de dépendances vide ([]), la requête est effectuée une seule fois au montage du composant. Si vous voulez refetcher des données lorsque certaines propriétés ou états changent, vous pouvez les inclure dans ce tableau.- Affichage Conditionnel : C'est la technique par excellence pour gérer les différents états d'une requête :
- Afficher un indicateur de chargement (
ActivityIndicator) tant queloadingesttrue. - Afficher un message d'erreur si
errorn'est pasnull. - Afficher les données réelles une fois qu'elles sont chargées et qu'il n'y a pas d'erreur.
- Afficher un indicateur de chargement (
Bonnes Pratiques et Sécurité
Intégrer des APIs est essentiel, mais le faire de manière sécurisée et performante l'est tout autant.
-
Gestion des Erreurs Robuste
- Distinguerez les erreurs réseau (pas de connexion, timeout) des erreurs API (404, 500, 401 Unauthorized).
- Informez l'utilisateur clairement en cas d'erreur (messages pertinents, toasts, alerts).
- Utilisez des blocs
try...catch...finallypour encapsuler vos requêtes.
-
Indicateurs de Chargement (UX)
- Toujours montrer un
ActivityIndicatorou un squelette de contenu pendant qu'une requête est en cours. Cela améliore considérablement l'expérience utilisateur en évitant l'impression que l'application est figée.
- Toujours montrer un
-
Gestion des Données Sensibles (Clés API, Tokens)
- NE JAMAIS coder en dur des clés API, des secrets ou des identifiants sensibles directement dans votre code source ou dans votre dépôt Git public.
- Utilisez des variables d'environnement pour stocker ces informations (par exemple, via la bibliothèque
react-native-dotenvou des configurations de build natives). - Pour les tokens d'authentification (JWT par exemple), stockez-les de manière sécurisée sur l'appareil (ex:
react-native-keychainpour iOS Keychain et Android Keystore) et incluez-les dans les en-têtes de vos requêtes (généralementAuthorization: Bearer VOTRE_TOKEN).
-
Découplage des Requêtes API (Services Dédicés)
- Ne mélangez pas la logique de requête API avec la logique de votre composant UI. Créez un dossier
servicesouapiavec des fichiers dédiés à chaque ressource ou groupe d'endpoints. - Exemple de structure :
- src/ - components/ - screens/ - api/ - axiosInstance.js // Configuration de base d'Axios (URL de base, intercepteurs) - auth.js // Fonctions pour l'authentification (login, register) - articles.js // Fonctions pour les articles (getArticles, createArticle) - users.js // Fonctions pour les utilisateurs (getUserProfile, updateUser) - App.js - Cela rend votre code plus maintenable, testable et réutilisable.
- Ne mélangez pas la logique de requête API avec la logique de votre composant UI. Créez un dossier
-
Limitation des Requêtes (Throttling/Debouncing)
- Si vous avez des fonctionnalités qui peuvent déclencher de nombreuses requêtes rapidement (ex: recherche en temps réel), utilisez des techniques de
throttling(limiter la fréquence d'exécution) ou dedebouncing(exécuter la fonction seulement après un certain délai d'inactivité) pour éviter de surcharger votre API et le réseau. Des bibliothèques commelodashoffrent ces utilitaires.
- Si vous avez des fonctionnalités qui peuvent déclencher de nombreuses requêtes rapidement (ex: recherche en temps réel), utilisez des techniques de
-
Caching
- Pour les données qui ne changent pas fréquemment, envisagez de mettre en cache les réponses côté client pour améliorer la performance et réduire les requêtes réseau. Des bibliothèques comme
React Query(TanStack Query) ouSWRpeuvent grandement simplifier la gestion du cache et de la synchronisation des données côté client.
- Pour les données qui ne changent pas fréquemment, envisagez de mettre en cache les réponses côté client pour améliorer la performance et réduire les requêtes réseau. Des bibliothèques comme
Conclusion
L'intégration d'APIs est la pierre angulaire des applications mobiles connectées. Vous avez maintenant une compréhension solide des concepts fondamentaux derrière les requêtes réseau (HTTP, JSON, asynchrone) et des outils clés disponibles dans React Native (fetch et Axios).
- Vous savez comment récupérer et envoyer des données en utilisant les méthodes
GETetPOST. - Vous êtes capable de gérer les états de chargement et d'erreur pour offrir une meilleure expérience utilisateur.
- Vous avez découvert l'importance de la gestion des erreurs et des bonnes pratiques de sécurité et de modularité.
La prochaine étape est la pratique ! Expérimentez avec différentes APIs, créez des interfaces utilisateur qui affichent des données dynamiques, et n'hésitez pas à approfondir les fonctionnalités avancées d'Axios ou d'autres bibliothèques de gestion de données. Le monde des applications connectées est à portée de main !