DEV Community

Cover image for Gestion efficace de l'état dans React à l'aide de l'API contextuelle et des hooks!
lawalalao
lawalalao

Posted on

Gestion efficace de l'état dans React à l'aide de l'API contextuelle et des hooks!

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

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>

Enter fullscreen mode Exit fullscreen mode

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" 
/>

Enter fullscreen mode Exit fullscreen mode

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;

Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;

Enter fullscreen mode Exit fullscreen mode

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

VMXVOFAAj.jpg

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;

Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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;
  }
};
Enter fullscreen mode Exit fullscreen mode

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";

Enter fullscreen mode Exit fullscreen mode

Envelopper le composant Library

<LibraryState>
  <Library />
</LibraryState>
Enter fullscreen mode Exit fullscreen mode

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;

Enter fullscreen mode Exit fullscreen mode

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
Linkedin
Dev
GitHub

Discussion (0)