Gestion efficace de l'état dans React à l'aide de l'API contextuelle et des hooks!
Tags: react, redux, reacthooks
Published: 2021-02-11 22:34:23

Salut les amis!
J'èspère vous allez bien. Dans mon article précédent ,j'ai parlé de la gestion des états dans les applications React ou j'ai parlé de l'API `context` .Dans cet article, je vais vous montrer comment vous pouvez créer une solution de gestion d'état simple mais fonctionnelle pour vos applications React. Nous utiliserons la nouvelle `API context` avec quelques `hooks` utiles pour construire ceci.

Lorsque j'ai essayé pour la première fois l'API context, j'étais confus quant à la meilleure façon de l'implémenter. De plus, je ne comprenais pas parfaitement les termes tels que fournisseurs (`providers`), consommateurs (`consumers`) , réducteurs (`reducers`), etc. qui m'étaient lancés dans chaque article en ligne que je lisais. J'ai donc hésité à utiliser cette solution simple dans les applications que je construisais.

Ce n'est que récemment que j'ai vraiment compris le concept de l'API de context et comment il peut être combiné avec des hooks pour créer une solution de gestion d'état assez puissante dans React. J'espère que dans ce billet de blog, je pourrai l'expliquer d'une manière très simple .

Commençons alors!

# À propos du projet

Pour ce billet, nous allons créer une application de bibliothèque très simple. L'idée n'est pas d'apprendre à créer des applications React, mais comment nous pouvons utiliser l'API context dans React. N'hésitez donc pas à copier le code de ces composants et à le coller dans votre propre projet. 

L'application se compose de 3 composants `Library`, `BookShelf` et `Book`. Nous voulons transmettre les données au composant `Book` sans transmettre de props. Nous allons donc utiliser l'API context pour cela.

Le code complet de ce projet se trouve sur mon GitHub: [Context-API-Demo](https://github.com/lawalalao/api-context)

Alors n'hésitez pas à y faire référence si vous êtes bloqué. 😉

## 1. Créez une application React

La première étape consiste à créer une application react de base. Nous utiliserons `create-react-app` pour le faire. Utilisez simplement la commande suivante pour créer votre projet react:

```
npx create-react-app <nom_de_votre_application>

```
Puisque je vais utiliser Bootstrap pour le style, vous pouvez également ajouter le cdn dans le fichier index.html comme suit:

```
<link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
      crossorigin="anonymous" 
/>

```
Génial! Vous pouvez maintenant ouvrir le projet dans votre éditeur de code préféré et passer à la deuxième étape.

# 2. Créez les composants

Maintenant, dans le répertoire `src`, créez un dossier appelé `components`. Nous placerons ici nos fichiers de composants. Ainsi dans ce dossier, créez les 3 fichiers suivants:

Library.js

```
import React from "react";
import BookShelf from "./bookShelf";

const Library = () => {
  return (
    <div className="pt-3">
      <p>
       Je suis dans le composant Library..
        <span role="img" aria-labelledby="emoji">
          ⚡
        </span>
      </p>
      <BookShelf />
    </div>
  );
};

export default Library;

```
BookShelf.js

```
import React from "react";
import Book from "./book";

const BookShelf = () => {
  return (
    <React.Fragment>
      <p>
       Je suis dans le composant bibliothèque
        <span role="img" aria-labelledby="emoji">
          🚀
        </span>
      </p>
      <Book />
    </React.Fragment>
  );
};

export default BookShelf;
```
Book.js

```
import React, { useContext } from "react";
import LibraryContext from "../context/libraryContext";

const Book = () => {

  return (
    <React.Fragment>
      <p>
        Salut, je suis un livre dans la bibliothèque. Mes informations proviennent de context!
        <span role="img" aria-labelledby="emoji">
          🧱
        </span>
      </p>
    </React.Fragment>
  );
};

export default Book;
```

Ici, nous ne faisons rien d'extraordinaire. Je fais juste 3 composants très basiques. Le composant `BookShelf` contient le composant `Book` et la `Library` contient le composant `BookShelf`.

Enfin, ajoutez le code suivant à App.js:

```
import React from "react";
import Library from "./components/library";

const App = () => {
  return (
    <React.Fragment>
      <div className="container-fluid pt-4 pl-4">
        <h2>
          React Context API Demo
          <span role="img" aria-labelledby="emoji">
            🔥
          </span>
        </h2>
        <Library />
      </div>
    </React.Fragment>
  );
}

export default App;

```
Ici, nous rendons le composant `Library` dans le composant `App`. Notre arborescence de composants ressemble à ceci:


![VMXVOFAAj.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1611875590527/CXsbmnp6O.jpeg)

## 3. Implémentation de l'API context

Vient maintenant la partie amusante: implémenter l'API context. Tout d'abord, créez un nouveau dossier dans `src` appelé `context`. J'aime conserver tous les fichiers de contexte dans ce dossier. Dans le dossier, nous créerons 3 fichiers. Ces fichiers sont: `LibraryContext.js`, `LibraryState.js` et `LibraryReducer.js`. Vous pouvez mélanger tout cela dans un seul fichier, mais cela deviendrait rapidement déroutant. Donc, j'aime garder tous ces éléments séparés car ils gèrent des fonctionnalités différentes.

Voyons d'abord comment fonctionnera notre gestion étatique. Ensuite, nous remplirons ces fichiers.

**Contexte de Library.**

Le LibraryContext créera le contexte et l'exportera. C'est ça. Rien de plus. Voici le code pour cela:

```
import { createContext } from "react";

// create a context
const LibraryContext = createContext();

export default LibraryContext;

```

Nous utilisons la fonction intégrée `createContext()` pour créer un contexte, puis nous l'exportons en tant qu'export par défaut.

**Etat de Library**

Dans le composant `LibraryState`, nous allons d'abord **créer notre état initial**. Ensuite, nous utiliserons le hook `useReducer` pour ajouter un **réducteur ** à notre état initial. Cela nous donnera la méthode de répartition **dispatch** qui peut être utilisée pour envoyer des actions au réducteur.

Laissez-moi vous expliquer comment cela fonctionne. Chaque fois que nous voulons mettre à jour l'état, nous utilisons la répartition **dispatch **pour déclencher une action vers le réducteur. Le réducteur **met alors à jour **notre état et renvoie le nouvel état. Ce modèle est similaire à celui utilisé par **Redux**.

Enfin, nous retournons un composant `Provider` qui nous permettra **d'accéder à l'état** **n'importe où** dans notre application. Tout ce que nous avons à faire est d'envelopper le composant avec notre composant `LibraryState` et nous aurons accès à l'état à l'intérieur de ce composant.

Regardons le code pour cela:

```
import React, { useReducer } from "react";
import { LibraryReducer } from "./libraryReducer";
import LibraryContext from "./libraryContext";

// create a provider component
const LibraryState = (props) => {
  // create initial state
  const initialState = {
    name: "Harry Potter and the Goblet of fire 🧙‍♂️",
    quantity: 7,
    shelf: "3A",
  };

  // useReducer() hook
  const [state, dispatch] = useReducer(LibraryReducer, initialState);

  // actions to manipulate state
  const incrementQuantity = () => {
    dispatch({
      type: "INCREMENT_QUANTITY",
    });
  };

  const resetQuantity = () => {
    dispatch({
      type: "RESET_QUANTITY",
    });
  };

  return (
    <LibraryContext.Provider
      value={{
        state: state,
        incrementQuantity: incrementQuantity,
        resetQuantity: resetQuantity,
      }}
    >
      {props.children}
    </LibraryContext.Provider>
  );
};

export default LibraryState;
```

Comme vous pouvez le voir, nous transmettons la **valeur** à l'intérieur du fournisseur à laquelle tous les composants à l'intérieur peuvent accéder. Dans notre cas, cette valeur inclut l'état provenant de notre `useReducer` et les **2** méthodes pour manipuler cet état.

**Réducteur de Library.**
Dans le `LibraryReducer`, nous allons créer une fonction qui mettra à jour l'état en fonction des actions. Pour chaque action, il mettra à jour l'état en fonction du** type d'action**. Jetez un œil au code:

```
export const LibraryReducer = (state, action) => {
  switch (action.type) {
    case "INCREMENT_QUANTITY":
      return { ...state, quantity: state.quantity + 1 };
    case "RESET_QUANTITY":
      return { ...state, quantity: 0 };
    default:
      return state;
  }
};
```
Ici, nous **incrémentons** le nombre ou le **réinitialisons** en fonction du type d'action. Comme vous vous en souvenez peut-être, nous avons utilisé `dispatch` pour déclencher ces actions à l'intérieur du composant `LibraryState`.

## 4. Accès à l'état dans le composant Book.

Maintenant que notre context est prêt, tout ce que nous avons à faire est d'encapsuler le composant `Library` dans le composant `LibraryState` qui agit comme notre composant `Provider`. Et nous aurons accès à l'état à l'intérieur du composant `Library` et de ses enfants.

Rendez-vous sur `App.js` et apportez les modifications suivantes:

Importer LibraryState:

```
import LibraryState from "./context/libraryState";

```
Envelopper le composant `Library`

```
<LibraryState>
  <Library />
</LibraryState>
```
C'est ça! Nous pouvons maintenant accéder aux valeurs du composant Provider n'importe où dans le composant Library et tous ses enfants.

Pour la dernière étape, nous modifierons le composant Book pour accéder aux valeurs d'état et ajouterons quelques boutons pour incrémenter ou réinitialiser le compte également.

Copiez et collez ce qui suit dans le composant Book:

```
import React, { useContext } from "react";
import LibraryContext from "../context/libraryContext";

const Book = () => {
  // useContext() hook
  const context = useContext(LibraryContext);
  return (
    <React.Fragment>
      <p>
       Salut, je suis un livre dans la bibliothèque. Mes informations proviennent de context!
        <span role="img" aria-labelledby="emoji">
          🧱
        </span>
      </p>
      {/* Book Information */}
      <p>Book Name: {context.state.name} </p>
      <p>Quantity: {context.state.quantity}</p>
      <p>Book Shelf: {context.state.shelf}</p>
      <div>
        <button className="btn btn-primary" onClick={context.incrementQuantity}>
          Increment
          <span role="img" aria-labelledby="emoji">
            🙌
          </span>
        </button>
        <button className="ml-2 btn btn-dark" onClick={context.resetQuantity}>
          Reset
          <span role="img" aria-labelledby="emoji">
            🙈
          </span>
        </button>
      </div>
    </React.Fragment>
  );
};

export default Book;

```
Ici, nous utilisons le hook `useContext` pour extraire le contexte. Ensuite, nous accédons aux valeurs à l'intérieur du contexte et les affichons dans le composant. Depuis que nous avons passé l'`état` dans la valeur de notre fournisseur `provider`, nous accédons aux valeurs en tant que `context.state.value`.

Enfin, nous ajoutons **2** boutons pour incrémenter et réinitialiser le décompte et nous ajoutons les méthodes passées comme `onClick` aux boutons.

C'est ça! L'application est maintenant terminée. Vous pouvez voir les valeurs d'état affichées dans le composant Book sans avoir à transmettre aucun props. Et les boutons peuvent également être utilisés pour manipuler l'état.

# Sommaire

Voici un bref résumé  de mise en œuvre de context:


- 
Créez le contexte à l'aide de la méthode `createContext`.

- 
Créez le composant Provider avec les valeurs à transmettre comme état. Dans notre cas, le composant `Library State`.

- 
Créez des réducteurs pour manipuler l'état et attacher avec l'état à l'aide du hook `useReducer`.

- 
Enveloppez le composant où la valeur doit être accessible dans le composant `Provider`.

- 
Accéder aux valeurs à l'aide du hook `useContext`

**Suivez-moi sur le Web**

Quelques endroits où vous pouvez me trouver en ligne!

 [Twitter](https://twitter.com/AdechinaAlao) 
[Linkedin](https://www.linkedin.com/in/lawal-adechina-alao-168147188/)
 [Dev](https://dev.to/lawalalao) 
 [GitHub](https://github.com/lawalalao)