Redux vous aide à gérer l'état en le configurant au niveau mondial. Dans le didacticiel précédent, nous avons examiné de près l'architecture Redux et les composants intégrés de Redux tels que les actions, les créateurs d'action, le magasin et les réducteurs..
Dans ce deuxième article de la série, nous allons renforcer notre compréhension de Redux et nous appuyer sur ce que nous savons déjà. Nous allons commencer par créer une application Redux réaliste - une liste de contacts - plus complexe qu'un compteur de base. Cela vous aidera à renforcer votre compréhension du concept de magasin unique et de réducteurs multiples que j'ai présenté dans le didacticiel précédent. Ensuite, nous parlerons de la liaison de votre état Redux avec une application React et des meilleures pratiques à prendre en compte lors de la création d'un projet à partir de zéro..
Cependant, si vous n'avez pas lu le premier post, vous pouvez quand même suivre si vous connaissez les bases de Redux. Le code du tutoriel est disponible dans le référentiel et vous pouvez l'utiliser comme point de départ..
Nous allons créer une liste de contacts de base avec les fonctionnalités suivantes:
Voici à quoi ressemblera notre application:
Produit final - Liste de contacts VoirCouvrir tout d'un trait est difficile. Donc, dans cet article, nous allons nous concentrer uniquement sur la partie Redux consistant à ajouter un nouveau contact et à afficher le contact nouvellement ajouté. Du point de vue de Redux, nous allons initialiser l'état, créer le magasin, ajouter des réducteurs et des actions, etc..
Dans le prochain didacticiel, nous allons apprendre à connecter React et Redux et à distribuer des actions Redux à partir d’un serveur React. Dans la dernière partie, nous allons nous concentrer sur les appels API à l’aide de Redux. Cela inclut la récupération des contacts du serveur et la demande du serveur lors de l'ajout de nouveaux contacts. En dehors de cela, nous allons également créer une fonctionnalité de barre de recherche qui vous permet de rechercher tous les contacts existants..
Vous pouvez télécharger l'application de démonstration react-redux à partir de mon référentiel GitHub. Cloner le repo et utiliser le v1 branche comme point de départ. le v1 branch est très similaire au modèle create-react-app. La seule différence est que j'ai ajouté quelques répertoires vides pour organiser Redux. Voici la structure du répertoire.
. ├── package.json ├── public ├── README.md actions src ├── App.js composants conteneurs index.js ├── réducteurs magasin └── fil.lock
Alternativement, vous pouvez créer un nouveau projet à partir de zéro. Quoi qu'il en soit, vous devez avoir installé une base chauffante de base react et redux avant de pouvoir commencer..
C'est une bonne idée d'avoir d'abord un aperçu de l'arbre d'état. À mon avis, cela vous fera gagner beaucoup de temps à long terme. Voici un aperçu de l'arborescence d'état possible.
const initialState = contacts: contactList: [], newContact: name: ", nom de famille:", email: ", adresse:", téléphone: ", ui: // Tous les états liés à l'interface utilisateur ici. Par exemple: masquer / afficher les modaux, // cochez la case etc.
Notre magasin doit avoir deux propriétés-Contacts
et ui
. La propriété contacts prend en charge tous les états liés aux contacts, alors que la ui
gère l'état spécifique à l'interface utilisateur. Il n’existe aucune règle stricte dans Redux qui vous empêche de placer le ui
objet en tant que sous-état de Contacts
. N'hésitez pas à organiser votre état de manière à ce qu'il ait un sens pour votre application..
La propriété de contacts a deux propriétés imbriquées à l'intérieur-liste de contacts
et nouveau contact
. le liste de contacts
est un tableau de contacts, alors que nouveau contact
stocke temporairement les coordonnées pendant le remplissage du formulaire de contact. Je vais l'utiliser comme point de départ pour la création de notre superbe application de liste de contacts.
Redux n'a pas d'opinion sur la structure de votre application. Il existe quelques modèles populaires, et dans ce tutoriel, je parlerai brièvement de certains d'entre eux. Mais vous devez choisir un motif et vous y tenir jusqu'à ce que vous compreniez parfaitement comment toutes les pièces sont liées les unes aux autres..
Le modèle le plus courant que vous trouverez est la structure de fichiers et de dossiers de style Rails. Vous aurez plusieurs répertoires de niveau supérieur comme ceux ci-dessous:
L'image ci-dessous montre à quoi notre application pourrait ressembler si nous suivions ce modèle:
Le style Rails devrait fonctionner pour les applications de petite et moyenne taille. Toutefois, lorsque votre application grandit, vous pouvez envisager d'adopter l'approche de style de domaine ou d'autres alternatives populaires étroitement liées au style de domaine. Ici, chaque entité aura son propre répertoire et tout ce qui se rapporte à cette entité (domaine) sera à l'intérieur. L'image ci-dessous compare les deux approches, style Rails à gauche et domaine à droite.
Pour l'instant, allez-y et créez des répertoires pour Composants, des conteneurs, le magasin, réducteurs, et action. Commençons par le magasin.
Créons un prototype pourla le magasin et le réducteur premier. De notre exemple précédent, voici à quoi ressemblerait notre magasin:
const store = createStore (réducteur, contacts: contactlist: [], newContact: , ui: isContactFormHidden: true) const réducteur = (état, action) => switch (action.type) case "HANDLE_INPUT_CHANGE": pause; case "ADD_NEW_CONTACT": pause; case "TOGGLE_CONTACT_FORM": break; état de retour;
L'instruction switch a trois cas qui correspondent aux trois actions que nous allons créer. Voici une brève explication de ce que les actions sont destinées à.
HANDLE_INPUT_CHANGE
: Cette action est déclenchée lorsque l'utilisateur entre de nouvelles valeurs dans le formulaire de contact.AJOUTER UN NOUVEAU CONTACT
: Cette action est envoyée lorsque l'utilisateur soumet le formulaire.TOGGLE_CONTACT_FORM
: Il s'agit d'une action de l'interface utilisateur qui prend en charge l'affichage / le masquage du formulaire de contact.. Bien que cette approche naïve fonctionne, à mesure que l’application se développe, l’utilisation de cette technique présentera quelques inconvénients..
Pour résoudre le problème de réducteur unique, Redux utilise une méthode appelée combineRéducteurs qui vous permet de créer plusieurs réducteurs, puis de les combiner en une seule fonction de réduction. La fonction combineRéducteurs améliore la lisibilité. Donc, je vais diviser le réducteur en deux contactsRéducteur
et un uiReducer
.
Dans l'exemple ci-dessus, createStore
accepte un optionnel deuxième argument qui est l'état initial. Cependant, si nous allons diviser les réducteurs, nous pouvons déplacer l'ensemble Etat initial
vers un nouvel emplacement de fichier, par exemple réducteurs / initialState.js. Nous allons ensuite importer un sous-ensemble de Etat initial
dans chaque fichier réducteur.
Restructurons notre code pour résoudre les deux problèmes. Tout d’abord, créez un nouveau fichier appelé store / createStore.js et ajoutez le code suivant:
importer createStore à partir de 'redux'; importer rootReducer de '… / réducteurs /'; / * Crée une fonction appelée configureStore * / export, fonction par défaut configureStore () return createStore (rootReducer);
Ensuite, créez un réducteur de racine dans réducteurs / index.js comme suit:
importer combineReducers de 'redux' importer contactsReducer de './contactsReducer'; importer uiReducer de './uiReducer'; const rootReducer = combineReducers (contacts: contactsReducer, ui: uiReducer,) export default rootReducer;
Enfin, nous devons créer le code pour le contactsRéducteur
et uiReducer
.
importer initialState de './initialState'; exporter la fonction par défaut contactReducer (state = initialState.contacts, action) switch (action.type) / * Ajouter des contacts au tableau d'état * / case "ADD_CONTACT": return … state, contactList: [… state.contactList, state.newContact] / * Traitement de l'entrée pour le formulaire de contact. La charge utile (modifications d'entrée) est fusionnée avec l'objet newContact * / case "HANDLE_INPUT_CHANGE": return … state, newContact: … state.newContact,… action.payload default: return state;
importer initialState de './initialState'; fonction par défaut d'exportation uiReducer (state = initialState.ui, action) switch (action.type) / * Afficher / masquer le formulaire * / case "TOGGLE_CONTACT_FORM": return … state, isContactFormHidden:! state.isContactFormHidden default : état de retour;
Lorsque vous créez des réducteurs, gardez toujours à l'esprit les points suivants: un réducteur doit avoir une valeur par défaut pour son état et doit toujours renvoyer quelque chose. Si le réducteur ne respecte pas cette spécification, vous obtiendrez des erreurs..
Puisque nous avons couvert beaucoup de code, examinons les changements que nous avons apportés à notre approche:
combiner des réducteurs
un appel a été introduit pour relier les réducteurs de split.ui
objet sera manipulé par uiReducer
et l'état des contacts par le contactsRéducteur
. createStore
. Au lieu de cela, nous avons créé un fichier séparé appelé initialState.js. Nous importons Etat initial
puis en définissant l'état par défaut en faisant state = initialState.ui
. Voici le code pour le réducteurs / initialState.js fichier.
const initialState = contacts: contactList: [], newContact: name: ", nom de famille:", email: ", adresse:", téléphone: ",, ui: isContactFormHidden: true export default initialState;
Ajoutons quelques actions et créateurs d’actions pour ajouter des modifications au formulaire de traitement, ajouter un nouveau contact et basculer l’état de l’interface utilisateur. Si vous vous souvenez, les créateurs d'action ne sont que des fonctions qui renvoient une action. Ajoutez le code suivant dans actions / index.js.
export const addContact = () => return type: "ADD_CONTACT", export const handleInputChange = (nom, valeur) => return type: "HANDLE_INPUT_CHANGE", charge utile: [nom]: valeur export const toggleContactForm = () => return type: "TOGGLE_CONTACT_FORM",
Chaque action doit renvoyer une propriété de type. Le type est comme une clé qui détermine quel réducteur est appelé et comment l'état est mis à jour en réponse à cette action. La charge est optionnelle et vous pouvez l'appeler comme bon vous semble.
Dans notre cas, nous avons créé trois actions.
le TOGGLE_CONTACT_FORM
n'a pas besoin d'une charge utile, car chaque fois que l'action est déclenchée, la valeur de ui.isContactFormHidden
se change. Les actions à valeur booléenne ne nécessitent pas de charge utile.
le HANDLE_INPUT_CHANGE
l'action est déclenchée lorsque la valeur du formulaire change. Ainsi, imaginons par exemple que l'utilisateur remplisse le champ email. L'action reçoit alors "email"
et "[email protected]"
en tant qu'entrées, et la charge utile remise au réducteur est un objet qui ressemble à ceci:
email: "[email protected]"
Le réducteur utilise ces informations pour mettre à jour les propriétés pertinentes du nouveau contact
Etat.
La prochaine étape logique consiste à répartir les actions. Une fois les actions envoyées, l’état change en conséquence. Pour répartir les actions et obtenir l'arborescence d'état mise à jour, Redux propose certaines actions de magasin. Elles sont:
dispatch (action)
: Distribue une action pouvant potentiellement déclencher un changement d'état. getState ()
: Retourne l'arborescence d'état actuelle de votre application.abonné (auditeur)
: Un écouteur de modification appelé chaque fois qu'une action est envoyée et qu'une partie de l'arborescence d'état est modifiée. Dirigez-vous vers le index.js déposer et importer le configureStore
fonction et les trois actions que nous avons créées précédemment:
importer Réagir de 'réagir'; importer render de 'react-dom'; importer l'application depuis './App'; / * Importer le magasin Redux et les actions * / import configureStore depuis './store/configureStore'; import toggleContactForm, handleInputChange depuis './actions';
Ensuite, créez un le magasin
object et ajoutez un écouteur qui enregistre l'arbre d'état chaque fois qu'une action est envoyée:
const store = configureStore (); // Notez que subscribe () renvoie une fonction permettant de désenregistrer le écouteur. Const unsubscribe = store.subscribe (() => console.log (store.getState ()))
Enfin, envoyez quelques actions:
/ * renvoie isContactFormHidden renvoie false * / store.dispatch (toggleContactForm ()); / * renvoie isContactFormHidden renvoie false * / store.dispatch (toggleContactForm ()); / * met à jour l'état de l'objet contacts.newContact * / store.dispatch (handleInputChange ('email', '[email protected]')) unsubscribe;
Si tout fonctionne correctement, vous devriez le voir dans la console du développeur..
C'est tout! Dans la console du développeur, vous pouvez voir le magasin Redux en cours de journalisation, ainsi vous pouvez voir comment il change après chaque action..
Nous avons créé une application Redux simple pour notre application géniale de liste de contacts. Nous avons appris comment utiliser les réducteurs, diviser les réducteurs pour rendre la structure de notre application plus propre et rédiger des actions visant à transformer le magasin en mutation..
Vers la fin du message, nous avons souscrit à la boutique en utilisant le store.subscribe ()
méthode. Techniquement, ce n'est pas la meilleure façon de faire avancer les choses si vous allez utiliser React avec Redux. Il existe d'autres moyens optimisés de connecter le front-end de réaction à Redux. Nous allons couvrir ceux dans le prochain tutoriel.