Table of Contents
La gestion de l'état dans les projets complexes React Native peut rapidement devenir un défi à mesure que l'application se développe dans les fonctionnalités, les écrans et les dépendances de données. Sans stratégie claire, la gestion de l'état se décline souvent dans un réseau enchevêtré de propulseurs de forage, d'états locaux dispersés et de données incohérentes entre les composants. Redux, un conteneur d'état prévisible pour les applications JavaScript, est depuis longtemps une solution de passe-partout pour mettre de l'ordre dans ce chaos.
Qu'est-ce que Redux ?
Redux est une bibliothèque JavaScript open source inspirée à l'origine de Flux, un modèle d'architecture créé par Facebook pour les applications web côté client. Son objectif principal est de gérer l'état global d'une application d'une manière unique, immuable et prévisible. Redux impose un flux de données unidirectionnel strict qui rend les changements d'état transparents et faciles à raisonner. Les trois principes fondamentaux qui sous-tendent Redux sont :
- Source unique de vérité:[ L'état de l'application entier est stocké dans un arbre d'objets JavaScript uni dans un seul magasin. Cela élimine les incohérences et simplifie le débogage car il n'y a qu'un seul endroit pour chercher l'état actuel.
- L'état est en lecture seule:[ La seule façon de changer l'état est d'envoyer une action, qui est un objet JavaScript simple qui décrit ce qui s'est passé. Cela garantit qu'aucune partie de l'interface utilisateur ne peut accidentellement surcharger l'état.
- Les changements sont faits avec des fonctions pures :[ Pour spécifier comment l'arbre d'état est transformé par des actions, vous écrivez des réducteurs purs. Les réducteurs prennent l'état précédent et une action, et retournent l'état suivant sans muter l'état précédent.
L'architecture Redux tourne autour de trois principaux éléments de construction : le magasin, les actions et les réducteurs. Le magasin détient l'état et fournit des méthodes telles que , et . Les actions sont envoyées au magasin, et les réducteurs calculent le nouvel état.
Pourquoi utiliser Redux dans Réagir Native?
Les applications Natives réagissent souvent à des interactions complexes sur plusieurs écrans, des mises à jour en temps réel, des états d'authentification partagés et des données mises en cache à partir de nombreux paramètres de l'API. Redux s'attaque à ces défis en centralisant la gestion de l'état, en rendant l'architecture plus organisée et prévisible.
État centralisé et prévisible
Avec Redux, tous les états d'application vivent dans un seul magasin. Cela permet de suivre facilement les changements d'état au fil du temps en utilisant des outils comme les Redux DevTools, qui fournissent le débogage du voyage dans le temps, l'enregistrement d'action et l'inspection de l'état.
Amélioration du débogage et de l'expérience du développeur
Redux DevTools vous permet de rejouer des actions, d'inspecter l'état à tout moment et même de revenir aux états précédents. Ceci est inestimable lorsque vous diagnostiquez des bugs complexes liés à l'état. De plus, parce que les actions sont des objets simples et que les réducteurs sont des fonctions pures, écrire des tests unitaires pour la logique d'affaires devient simple.
Scalabilité pour les grandes équipes
Dans les grands projets avec plusieurs développeurs, Redux impose un modèle cohérent pour la circulation des données. Les nouveaux membres de l'équipe peuvent rapidement comprendre l'architecture en regardant le magasin, les actions et les réducteurs. La séparation des préoccupations entre les composants de l'interface utilisateur et la logique d'état signifie que les développeurs peuvent travailler sur différentes parties de l'application sans marcher sur le code des uns et des autres.
Soutien aux effets secondaires et aux flux de travail asynchrones
Les applications Natives réagissent fréquemment avec des API distantes, des fonctions de stockage local ou des dispositifs. Les middlewares Redux comme Redux Thunk (pour une logique async simple) et Redux Saga (pour une orchestration complexe) facilitent la manipulation des effets secondaires de manière claire et testable. Middleware agit comme un pipeline entre l'envoi d'une action et le moment où il atteint le réducteur, fournissant un emplacement central pour la manipulation des opérations async.
Portabilité et écosystème
Redux est framework-agnostic et peut être utilisé avec le JavaScript vanillé, React, React Native, Angular, Vue, et plus encore. L'écosystème Redux comprend des bibliothèques comme Redux Toolkit (la façon officielle recommandée d'écrire la logique Redux), Reselect (pour créer des sélecteurs mémorisés) et Redux Persist (pour avoir maintenu le magasin à AsyncStorage ou d'autres backends de stockage).
Cependant, Redux est également livré avec une courbe d'apprentissage et un code de plaque de chaudière. Pour les applications petites ou simples, la complexité supplémentaire peut ne pas être justifiée. Dans de tels cas, Reacts intégré API ou bibliothèque de gestion d'état légère comme Zustand ou Jotai pourrait être plus approprié. La décision d'utiliser Redux devrait être basée sur la complexité du projet, la taille de l'équipe et les besoins de maintenance à long terme.
Mettre Redux en œuvre dans un projet autochtone réagisse
L'intégration de Redux dans un projet React Native comporte une série d'étapes bien définies. Ci-dessous, un aperçu de haut niveau du processus, ainsi que des pratiques recommandées pour l'utilisation moderne de Redux.
Installation
Commencez par installer la bibliothèque Redux et la reliure React, ainsi que la boîte à outils Redux pour une configuration simplifiée :
npm install @reduxjs/toolkit react-redux
La trousse à outils Redux comprend des utilitaires comme , et qui réduisent considérablement la plaque de chaudière et appliquent les meilleures pratiques.
Création du Store
Créez un fichier (p. ex. ) et utilisez pour configurer le magasin. Cela combine automatiquement les réducteurs, ajoute des middlewares comme redux-thunk et permet au Redux DevTools de se développer.
import { configureStore } from '@reduxjs/toolkit';
import rootReducer from './reducers';
const store = configureStore({
reducer: rootReducer,
});
export default store;
Définir les actions et les réducteurs avec les tranches
Redux Toolkits vous permet de définir des actions et un réducteur ensemble dans un bloc concis. Chaque tranche représente un domaine logique de l'état de l'application (par exemple, utilisateur, paramètres, panier).
import { createSlice } from '@reduxjs/toolkit';
const userSlice = createSlice({
name: 'user',
initialState: { name: null, token: null },
reducers: {
setUser: (state, action) => {
state.name = action.payload.name;
state.token = action.payload.token;
},
clearUser: (state) => {
state.name = null;
state.token = null;
},
},
});
export const { setUser, clearUser } = userSlice.actions;
export default userSlice.reducer;
Parce que Redux Toolkit utilise la bibliothèque Immer en interne, vous pouvez écrire la logique de réduction qui semble muter l'état directement, mais il produit en fait des mises à jour immuables.
Connexion des composants au Store
Il existe deux façons principales de connecter les composants autochtones de React au magasin Redux : le legs HOC (composant de commande supérieure) et les crochets modernes React-Redux ( et . L'approche des crochets est recommandée pour un nouveau code.
Pour lire les données du magasin, utilisez avec une fonction de sélecteur :
import { useSelector } from 'react-redux';
const UserProfile = () => {
const userName = useSelector((state) => state.user.name);
return <Text>Hello, {userName}</Text>;
};
Pour envoyer des actions, utilisez :
import { useDispatch } from 'react-redux';
import { clearUser } from './userSlice';
const LogoutButton = () => {
const dispatch = useDispatch();
return <Button title="Logout" onPress={() => dispatch(clearUser())} />;
};
Enfin, enveloppez votre composant racine d'application avec le composant de React‐Redux et passez le magasin comme un accessoire :
import { Provider } from 'react-redux';
import store from './store';
const App = () => (
<Provider store={store}>
<MainNavigator />
</Provider>
);
Meilleures pratiques pour utiliser Redux dans les projets complexes
Lorsque vous travaillez avec de grandes bases de codes React Native, il est essentiel de suivre des pratiques éprouvées pour maintenir la qualité et la performance des codes. Voici les meilleures pratiques critiques, dont beaucoup sont encouragées par le Guide officiel de style Redux.
Normaliser la forme de l'État
Les données du magasin Redux doivent être structurées comme une base de données : plate et sans duplication. Par exemple, si vous avez une liste de messages et leurs auteurs, stockez les messages et les auteurs séparément et les référez par ID. La normalisation empêche les incohérences de données et simplifie les mises à jour.
Utilisez la boîte à outils Redux (RTK)
En 2024, Redux Toolkit est la façon officielle et avisée d'écrire la logique Redux. Il élimine la plupart des plaques de chaudière associées à Redux traditionnel, comprend le support intégré pour les mises à jour immuables avec Immer, et s'intègre parfaitement avec Redux DevTools. RTK-S gère le cycle de vie des demandes asynchrones (en attente, remplies, rejetées) avec un code minimal.
Écrire des réducteurs purs
Même si Redux Toolkit permet un code mutable via Immer, les réducteurs doivent rester des fonctions pures : ils ne doivent pas effectuer d'effets secondaires ou appeler des fonctions non pures (p. ex. , .
Leverage Middleware pour Effets secondaires
Utilisez le middleware pour gérer la logique asynchrone, les appels API, la logarithme, le rapport d'accident ou tout autre effet secondaire. Redux Thunk (inclus avec RTK) est suffisant pour la plupart des projets. Pour les flux complexes impliquant des séquences, le débonflage ou l'annulation, considérez Redux Saga. Middleware garde les réducteurs propres et testables.
Utiliser des sélecteurs mémorisés
Dériver les données du magasin en utilisant des sélecteurs et les mémoriser avec la bibliothèque Reselect (réexportée sous de @reduxjs/toolkit). La mémorisation empêche les recomputations inutiles lorsque l'état d'entrée n'a pas changé.
Tapez le Store avec TypeScript
TypeScript ajoute un filet de sécurité pour la gestion de l'état de Redux. Définissez la forme de votre état, actions et réducteurs avec des types précis. Redux Toolkit fournit un excellent support TypeScript, y compris les types inférés pour les tranches et le magasin. Cela capture de nombreuses erreurs d'exécution au moment de la compilation et améliore la productivité du développeur.
Distribuer les tranches de magasin par fonction
Organisez votre magasin en tranches logiques (p. ex. , , ) plutôt que par rôle technique (actions, réducteurs, constantes). Ce regroupement basé sur les fonctionnalités facilite la navigation et l'entretien de la base de codes. Chaque tranche peut également avoir ses propres sélecteurs et des bourrelets.
Actions d'essai et réducteurs
Comme les réducteurs sont des fonctions pures, les tests unitaires sont simples. Ecrire des tests qui vérifient les transitions d'état correctes pour chaque type d'action. Pour les thunks ou les sagas, les tests d'intégration qui simulent les appels d'API et vérifient les actions finales expédiées sont également importants.
Optimiser les performances
Dans React Native, les ré-reveurs inutiles peuvent dégrader l'expérience utilisateur. Assurez-vous que les composants ne se renaissent que lorsque la tranche exacte de l'état dépend des changements. Utilisez avec une égalité peu profonde (via ] de responsive-redux) lors de la sélection des objets, ou préférez sélectionner des valeurs primitives.
Considérations avancées
Au-delà des bases, les applications du monde réel nécessitent souvent des fonctionnalités et des modèles supplémentaires.Cette section explore des sujets plus avancés qui sont pertinents pour des projets autochtones complexes de Réact.
Flux de données asynchrone avec createAsyncThunk
Lors de la récupération des données d'une API, vous devez généralement gérer trois états : chargement, succès et erreur. Redux Toolkit , envoie automatiquement des types d'action en attente, rempli et rejeté. Exemple :
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
export const fetchPosts = createAsyncThunk(
'posts/fetchPosts',
async (userId) => {
const response = await api.getPosts(userId);
return response.data;
}
);
Les actions générées peuvent ensuite être gérées dans les réducteurs slices en utilisant le champ , vous permettant de mettre à jour les drapeaux de chargement et les messages d'erreur.
Persisting the Redux Store
Pour les applications hors ligne ou pour préserver l'état à travers les redémarrages de l'application, utilisez Redux Persist. Il enregistre automatiquement un sous-ensemble du magasin dans un moteur de stockage (AsyncStorage ou Reaction-native-mmkv). La configuration est simple, et vous pouvez sélectionner ou noir-liste des tranches spécifiques. Cependant, soyez prudents quant à la persistance de grandes quantités de données – utilisez la persistance sélective et envisagez des stratégies de migration pour les changements de schéma.
Annuler/Redo et mettre à jour de manière optimale
En stockant un historique d'instantanés d'état (ou des séquences d'actions), vous pouvez revenir aux états précédents. Des mises à jour optimistes – où les mises à jour de l'interface utilisateur immédiatement avant le serveur confirme – peuvent également être gérées avec Redux en adressant une action en attente de -- et ensuite soit confirmer ou faire revenir en arrière en fonction de la réponse du serveur.
Mises à jour en temps réel avec WebSockets
Les applications comme le chat ou les flux en direct nécessitent des poussées de données en temps réel. Vous pouvez intégrer les auditeurs WebSocket dans les middlewares ou les thunks qui envoient des actions quand de nouvelles données arrivent. Les canaux d'événements Redux Saga , sont particulièrement adaptés à cela, mais un middleware personnalisé qui gère le cycle de vie WebSocket fonctionne également.
Solutions de rechange à Redux dans Réagir Native
Bien que Redux soit un vétéran du paysage de la gestion de l'État, plusieurs solutions modernes sont apparues qui peuvent être mieux adaptées à certains types de projets.
Réagir API contextuel + utilisationRéducteur
L'API contextuelle intégrée Reacts, combinée au crochet , peut être une solution de rechange plus simple pour les petites et moyennes applications. Elle ne nécessite pas de bibliothèques supplémentaires. Cependant, le contexte a quelques limites : il peut causer des re-rendeurs inutiles, ne permet pas l'intégration de DevTools hors de la boîte et ne s'adapte pas bien lorsque de nombreux contextes sont imbriqués.
Zustand
Zustand est une bibliothèque de gestion d'état minimaliste qui offre un flux de données unidirectionnel similaire à Redux mais avec beaucoup moins de plaque de chaudière. Il ne fait pas appliquer un seul magasin, et son API est basé sur des crochets. Zustand est idéal pour les projets qui veulent les avantages d'un magasin centralisé sans la cérémonie des actions et des réducteurs.
Jotai et Recoil
Jotai et Recoil adoptent une approche atomique de la gestion de l'état, où l'état est brisé en petites unités indépendantes appelées atomes. Ces bibliothèques sont idéales pour la réactivité fine; elles permettent aux composants de s'abonner uniquement aux atomes dont ils ont besoin. Recoil, développé par Facebook, s'intègre profondément à React, mais il est encore expérimental et a un support limité pour les environnements non-Réact. Jotai est plus mature et léger.
MobX
MobX utilise un état observable et une dérivation automatique, ce qui le rend plus -magical -- que Redux. Il peut être plus simple d'écrire pour certaines applications data-havey, mais sa dépendance à l'état mutable peut conduire à des problèmes plus difficiles à déboguer. Il manque également le même niveau d'outils DevTools et d'outils communautaires que Redux.
Choisissez l'outil qui correspond le mieux à votre équipe, la complexité de la logique d'état, et le besoin d'outils de débogage. Pour les projets de grande entreprise avec de nombreux développeurs et des exigences de test strictes, Redux (avec Redux Toolkit) reste un choix solide et éprouvé.
Conclusion
Redux fournit un cadre robuste et éprouvé pour gérer l'état complexe dans les projets React Native. En centralisant l'état, en faisant fonctionner un flux de données unidirectionnel et en offrant de puissants outils de middleware et de développeur, Redux aide les équipes à construire des applications évolutives, durables et prévisibles. Les pratiques modernes, en particulier celles promues par Redux Toolkit, ont réduit considérablement la plaque de chaudière une fois associée à Redux, la rendant plus accessible que jamais. Pour les applications React Natives à grande échelle avec un large partage de données intercomposantes, des workflows asynchrones et le besoin de fonctionnalités avancées comme le débogage du temps de voyage, Redux est un choix convaincant. Cependant, aucune solution n'est un modèle unique. Évaluer les exigences spécifiques de votre projet, l'expérience de l'équipe et les objectifs de maintenance à long terme avant de s'engager dans une stratégie de gestion d'État.