Comment déplacer des applications iPhone d'un écran d'accueil vers la bibliothèque d'applications
17 septembre 2020
Les clients de Google Fiber peuvent bientôt déchiqueter Internet à des vitesses de 2 Gbps – Review Geek
17 septembre 2020

Logo Redux

Redux est un outil de gestion d'état, spécialement conçu pour les applications JavaScript côté client qui dépendent fortement de données complexes et d'API externes, et fournit d'excellents outils de développement qui facilitent le travail avec vos données.

Que fait Redux?

En termes simples, Redux est un magasin de données centralisé. Toutes vos données d'application sont stockées dans un seul grand objet. le Redux Devtools rendre cela facile à visualiser:

Un magasin de données Redux visualisé

Cet état est immuable, ce qui est un concept étrange au début, mais qui a du sens pour plusieurs raisons. Si vous souhaitez modifier l'état, vous devez envoyer un action, qui prend essentiellement quelques arguments, forme une charge utile et l'envoie à Redux. Redux passe l'état actuel à un réducteur , qui modifie l'état existant et renvoie un nouvel état qui remplace l'état actuel et déclenche un rechargement des composants affectés. Par exemple, vous pouvez avoir un réducteur pour ajouter un nouvel élément à une liste, ou supprimer ou modifier un élément qui existe déjà.

En procédant de cette façon, vous n'obtiendrez jamais de comportement indéfini avec l'état de modification de votre application à volonté. De plus, comme il existe un enregistrement de chaque action et de ce qu'elle a changé, cela permet le débogage dans le temps, où vous pouvez faire défiler l'état de votre application pour déboguer ce qui se passe avec chaque action (un peu comme un historique git).

Un enregistrement de chaque action

Redux peut être utilisé avec n'importe quel framework frontend, mais il est couramment utilisé avec React, et c'est ce sur quoi nous allons nous concentrer ici. Sous le capot, Redux utilise React API de contexte, qui fonctionne de la même manière que Redux et convient aux applications simples si vous souhaitez renoncer complètement à Redux. Cependant, les Devtools de Redux sont fantastiques lorsque vous travaillez avec des données complexes, et ils sont en fait plus optimisés pour éviter les rediffusions inutiles.

Si vous utilisez TypeScript, les choses sont beaucoup plus compliquées pour que Redux soit strictement typé. Vous voudrez suivre ce guide à la place, qui utilise actions-sûres pour gérer les actions et les réducteurs d'une manière conviviale.

Structurer votre projet

Tout d'abord, vous souhaiterez mettre en page la structure de vos dossiers. Cela dépend de vous et des préférences de style de votre équipe, mais il existe essentiellement deux modèles principaux que la plupart des projets Redux utilisent. La première consiste simplement à diviser chaque type de fichier (action, réducteur, middleware, effet secondaire) dans son propre dossier, comme ceci:

boutique/
  Actions/
  réducteurs /
  sagas /
  middleware /
  index.js

Ce n’est cependant pas le meilleur, car vous aurez souvent besoin à la fois d’un fichier d’action et d’un fichier de réduction pour chaque fonctionnalité que vous ajoutez. Il est préférable de fusionner les dossiers des actions et des réducteurs et de les diviser par fonctionnalité. De cette façon, chaque action et le réducteur correspondant sont dans le même fichier. Tu

boutique/
  fonctionnalités/
    faire/
    etc/
  sagas /
  middleware /
  root-reducer.js
  root-action.js
  index.js

Cela nettoie les importations, car vous pouvez maintenant importer les actions et les réducteurs dans la même instruction en utilisant:

import {todosActions, todosReducer} depuis 'store / features / todos'

C'est à vous de décider si vous souhaitez conserver le code Redux dans son propre dossier (/boutique dans les exemples ci-dessus) ou intégrez-le dans le dossier racine src de votre application. Si vous séparez déjà le code par composant et que vous écrivez de nombreuses actions personnalisées et réducteurs pour chaque composant, vous souhaiterez peut-être fusionner les /fonctionnalités/ et /Composants/ et stockez les composants JSX avec le code réducteur.

Si vous utilisez Redux avec TypeScript, vous pouvez ajouter un fichier supplémentaire dans chaque dossier d'entités pour définir vos types.

Installation et configuration de Redux

Installez Redux et React-Redux depuis NPM:

npm installer redux react-redux

Vous voudrez probablement aussi redux-devtools:

npm install --save-dev redux-devtools

La première chose que vous voudrez créer est votre boutique. Enregistrez ceci sous /store/index.js

importer {createStore} depuis 'redux'
importer rootReducer depuis './root-reducer'

const store = createStore (rootReducer)

exporter le magasin par défaut;

Bien sûr, votre boutique deviendra plus compliquée que cela à mesure que vous ajouterez des éléments tels que des addons d'effets secondaires, des intergiciels et d'autres utilitaires tels que connecté-react-router, mais c’est tout ce qui est nécessaire pour le moment. Ce fichier prend le réducteur racine et appelle createStore () en l'utilisant, qui est exporté pour que l'application puisse l'utiliser.

Ensuite, nous allons créer une fonctionnalité simple de liste de tâches. Vous voudrez probablement commencer par définir les actions requises par cette fonctionnalité et les arguments qui leur sont transmis. Créer un / fonctionnalités / todos / dossier et enregistrez ce qui suit sous types.js:

export const ADD = 'ADD_TODO'
export const DELETE = 'DELETE_TODO'
export const EDIT = 'EDIT_TODO'

Cela définit quelques constantes de chaîne pour les noms d'action. Quelles que soient les données que vous transmettez, chaque action aura un type property, qui est une chaîne unique qui identifie l'action.

Vous n'êtes pas obligé d'avoir un fichier de type comme celui-ci, car vous pouvez simplement taper le nom de chaîne de l'action, mais il est préférable pour l'interopérabilité de le faire de cette façon. Par exemple, vous pourriez avoir todos.ADD et rappels.ADD dans la même application, ce qui vous évite d'avoir à taper _FAIRE ou _RAPPEL chaque fois que vous faites référence à une action pour cette fonctionnalité.

Ensuite, enregistrez ce qui suit sous /store/features/todos/actions.js:

import * en tant que types de './types.js'

export const addTodo = text => ({type: types.ADD, texte})
export const deleteTodo = id => ({type: types.DELETE, id})
export const editTodo = (id, texte) => ({type: types.EDIT, id, texte})

Cela définit quelques actions en utilisant les types des constantes de chaîne, en présentant les arguments et la création de charge utile pour chacun. Celles-ci ne doivent pas nécessairement être entièrement statiques, car ce sont des fonctions. Un exemple que vous pourriez utiliser est la définition d'un environnement d'exécution CUID pour certaines actions.

Le morceau de code le plus compliqué, et où vous implémenterez la plupart de votre logique métier, se trouve dans les réducteurs. Celles-ci peuvent prendre plusieurs formes, mais la configuration la plus couramment utilisée est une instruction switch qui gère chaque cas en fonction du type d'action. Enregistrez ceci sous reducer.js:

import * en tant que types de './types.js'

const initialState = (
  {
    texte: 'Hello World',
    identifiant: 0
  }
)

Exporter les todos de la fonction par défaut (state = initialState, action) {
  commutateur (action.type) {
    types de cas.
      revenir (
        ...Etat,
        {
          id: state.reduce ((maxId, todo) => Math.max (todo.id, maxId), -1) + 1,
          texte: action.text
        }
      )

    types de cas. SUPPRIMER:
      return state.filter (todo =>
        todo.id! == action.id
      )

    types de cas.
      return state.map (todo =>
        todo.id === action.id? {... todo, text: action.text}: todo
      )

    défaut:
      état de retour
  }
}

L'état est passé en argument et chaque cas renvoie une version modifiée de l'état. Dans cet exemple, ADD_TODO ajoute un nouvel élément à l'état (avec un nouvel identifiant à chaque fois), DELETE_TODO supprime tous les éléments avec l'ID donné, et EDIT_TODO mappe et remplace le texte de l'élément par l'ID donné.

L'état initial doit également être défini et transmis à la fonction de réduction comme valeur par défaut pour la variable d'état. Bien sûr, cela ne définit pas toute la structure d’états de Redux, seulement le state.todos section.

Ces trois fichiers sont généralement séparés dans des applications plus complexes, mais si vous le souhaitez, vous pouvez également les définir tous dans un seul fichier, assurez-vous simplement que vous importez et exportez correctement.

Une fois cette fonctionnalité terminée, connectons-la à Redux (et à notre application). Dans /store/root-reducer.js, importez le todosReducer (et tout autre réducteur de fonctionnalités du /fonctionnalités/ dossier), puis transmettez-le à combinerRéducteurs (), formant un réducteur racine de niveau supérieur qui est transmis au magasin. C'est ici que vous configurerez l'état racine, en veillant à conserver chaque fonctionnalité sur sa propre branche.

import {combineReducers} de 'redux';

importer todosReducer depuis './features/todos/reducer';

const rootReducer = combineReducers ({
  todos: todosReducer
})

exporter rootReducer par défaut

Utilisation de Redux dans React

Bien entendu, rien de tout cela n’est utile s’il n’est pas connecté à React. Pour ce faire, vous devrez encapsuler l'intégralité de votre application dans un Fournisseur composant. Cela garantit que l'état et les hooks nécessaires sont transmis à chaque composant de votre application.

Dans App.js ou index.js, partout où vous avez votre fonction de rendu racine, enveloppez votre application dans un , et passez-le au magasin (importé de /store/index.js) comme accessoire:

importer React depuis 'react';
importer ReactDOM depuis 'react-dom';

// Configuration de Redux
import {Provider} de 'react-redux';
import store, {historique} de './store';

ReactDOM.render (
    
       

    
    
    , Document.getElementById ('racine'));

Vous êtes désormais libre d'utiliser Redux dans vos composants. La méthode la plus simple consiste à utiliser des composants de fonction et des crochets. Par exemple, pour envoyer une action, vous utiliserez le useDispatch () hook, qui vous permet d'appeler directement des actions, par exemple dispatch (todosActions.addTodo (texte)).

Le conteneur suivant a une entrée connectée à l'état React local, qui est utilisée pour ajouter une nouvelle tâche à l'état chaque fois qu'un bouton est cliqué:

import React, {useState} de 'react';

import './Home.css';

importer {TodoList} à partir de 'composants'
importer {todosActions} depuis 'store / features / todos'
importer {useDispatch} depuis 'react-redux'

function Accueil () {
const dispatch = useDispatch ();
const (texte, setText) = useState ("");

function handleClick () {
dispatch (todosActions.addTodo (texte));
Définir le texte("");
}

function handleChange (e: React.ChangeEvent) {
setText (e.target.value);
}

revenir (
    
); } exporter la maison par défaut;

Ensuite, lorsque vous souhaitez utiliser les données stockées dans l'état, utilisez le useSelector crochet. Cela prend une fonction qui sélectionne une partie de l'état à utiliser dans l'application. Dans ce cas, il définit le Publier variable à la liste actuelle des tâches. Ceci est ensuite utilisé pour rendre un nouvel élément todo pour chaque entrée dans state.todos.

importer React depuis 'react';
importer {useSelector} depuis 'store'

import {Container, List, ListItem, Title} depuis './styles'

function TodoList () {
const posts = useSelector (état => state.todos)

revenir (
    
      
        
        {posts.map (({id, title}) => (
          
            {title}: {id}
          
        
        ))}
      
    
  
  );
}

exporter TodoList par défaut;

Vous pouvez réellement créer fonctions de sélection personnalisées pour gérer cela pour vous, enregistré dans le /fonctionnalités/ dossier tout comme les actions et les réducteurs.

Une fois que vous avez tout mis en place et compris, vous voudrez peut-être vous pencher sur la configuration Redux Devtools, la configuration de middleware comme Redux Logger ou connecté-react-router, ou l'installation d'un modèle d'effets secondaires tel que Redux Sagas.

//]]>