React : API Context

le

L’API context a toujours été – jusqu’à il y a peu, synonyme de danger, de fin du monde dans une application React. Même la documentation faisait tout pour nous dissuader de l’utiliser. Pourtant, il n’y a rien de plus usant que de devoir passer ses props d’un container à un enfant d’un enfant d’un enfant d’un enfant. C’est notamment le cas lorsque l’on a des props qui sont globales, et qu’on veut les utiliser un peu partout.

Avec l’arrivée de React 16.3, on a enfin une API utilisable qui ne risque pas de péter d’une mise à jour à une autre, et qui apporte son lot de nouvelles features.

Avant

Imaginons que votre application soit un forum, et que vous souhaitiez mettre en avant des fonctionnalités spécifiques à l’utilisateur connecté afin  :

  • qu’il puisse éditer son post dans un topic
  • qu’il puisse supprimer son post
  • avoir un repère visuel sur les posts dont il est l’auteur

La structure de l’application pourrait ressembler à ceci :

  • board (container)
    • topics (component)
      • posts (component)
        • post (component)

Dans une application React / Redux, vous avez un container qui va servir à passer les informations de l’user et ses posts sous forme de props aux composants enfants. Ici ce sera probablement le container board qui jouera le rôle de container et qui peut potentiellement utiliser Redux, tandis que les composants recevront ses props.

On se retrouverait à devoir passer l’user de board jusqu’à post sous forme de props :

<Topics currentUser={currentUser} />

Puis…

<Posts currentUser={currentUser} />

Puis…

<Post currentUser={currentUser} />

Sachant qu’on a besoin de la prop currentUser uniquement dans le composant <Post />, ça devient rapidement lourdingue, d’autant qu’on devra déclarer le type sur chaque composant. Overkill.

Un exemple de ce que ça donne sur ce repo : https://github.com/GregoryBabonaux/react-context-api-demo

Je confirme, j’ai fait aucun effort pour le design.

Après

Avec l’API Context, on peut faire nettement plus simple en créant un… context  basé sur un Provider et un Consumer. Le Provider va encapsuler nos composants enfants et leur permettre d’accéder à ses valeurs via le composant Consumer qui souscrit aux modifications du Provider.

Dans notre container Board, on va arrêter de passer notre currentUser en props. A la place, on va créer un composant BoardContext dans lequel on va pouvoir passer nos valeurs :

export const BoardContext = React.createContext({
  currentUser: null,
});

Puis on pourra l’utiliser comme ceci dans notre container Board :

<BoardContext.Provider value={{ currentUser }}>
  <Topics topics={topics} />
</BoardContext.Provider>

Désormais, on peut virer toutes les références à la prop currentUser dans les composants, puis, dans le composant qui nous intéresse, utiliser directement le currentUser en consommant l’API Context. On importe notre composant BoardContext dans Post :

import { BoardContext } from './Board';

Puis on prend la valeur qui nous intéresse :

<BoardContext.Consumer>{({ currentUser}) => 
  // Faites ce que vous voulez avec currentUser
}
</BoardContext.Consumer>

Vous retrouverez le code ici : https://github.com/GregoryBabonaux/react-context-api-demo/tree/context-api

En deux mots

L’API Context a un sacré potentiel pour gagner en lisibilité tout en évitant les tâches répétitives (et par conséquent sujettes à des tonnes d’erreurs ou d’incompréhension). On peut aller nettement plus loin en mettant par exemple en place un système de thème (le web foisonne d’articles à ce sujet).

Le fonctionnement est assez compréhensible pour savoir rapidement d’où viennent les valeurs qu’on souhaite utiliser. Dans mon exemple, il ne faut pas longtemps pour comprendre que currentUser vient du composant Board, reste ensuite à suivre la logique du Provider pour retrouver ces petits.

Have fun !

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *