Apprendre le contexte React en 5 minutes - Tutoriel pour débutant

L'API de contexte de React est devenue l'outil de gestion d'état de choix pour beaucoup, remplaçant souvent Redux. Dans ce rapide didacticiel de 5 minutes, vous verrez une introduction à ce qu'est le contexte et comment l'utiliser!

Si vous voulez une bonne introduction à ce sujet, vous pouvez vous inscrire sur la liste d'attente de mon prochain cours avancé React, ou si vous êtes encore un débutant, consultez mon cours d'introduction gratuit sur React.

Considérez cet arbre, dans lequel les cases du bas représentent des composants séparés:

Arborescence des composants

Nous pouvons facilement ajouter un état aux composants inférieurs, mais jusqu'à présent, le seul moyen de transmettre des données au frère d'un composant était de déplacer l'état vers un composant supérieur, puis de le transmettre au frère via des accessoires.

Passer des données via des accessoires

Si nous découvrons plus tard que le frère du composant avec l'état a également besoin des données, nous devons lever l'état à nouveau et le transmettre:

Passer l'état à travers plusieurs niveaux

Bien que cette solution fonctionne, les problèmes commencent si un composant d'une autre branche a besoin des données:

Un composant plus éloigné nécessite des données

Dans ce cas, nous devons passer l'état du niveau supérieur de l'application à travers tous les composants intermédiaires à celui qui a besoin des données en bas, même si les niveaux intermédiaires n'en ont pas besoin. Ce processus fastidieux et chronophage est connu sous le nom de forage d'étai .

Forage d'hélice

C'est là qu'intervient l'API de contexte. Elle permet de transmettre des données à travers l'arborescence des composants via une paire fournisseur-consommateur sans avoir à transmettre des accessoires à chaque niveau. Considérez-le comme les composants jouant à Catch avec des données - les composants intermédiaires peuvent même ne pas «savoir» que quelque chose se passe:

Contexte en action

Pour démontrer cela, nous allons créer cette image de commutation de jour en nuit géniale (et super utile).

Si vous voulez voir le code complet, assurez-vous de consulter le terrain de jeu Scrimba pour cet article.

Créer un contexte

Pour commencer, nous créons un nouveau contexte. Comme nous voulons que l'ensemble de l'application y ait accès, nous allons index.jset enveloppons l'application ThemeContext.Provider.

Nous transmettons également l' valueaccessoire à notre fournisseur. Cela contient les données que nous voulons enregistrer. Pour l'instant, nous nous contentons de coder en dur 'Day'.

import React from "react"; import ReactDOM from "react-dom"; import ThemeContext from "./themeContext"; import App from "./App"; ReactDOM.render(   , document.getElementById("root") ); 

Consommer le contexte avec contextType

Actuellement, dans App.js, nous retournons simplement le composant.

import React from "react"; import Image from "./Image"; class App extends React.Component { render() { return ( ); } } export default App; 

Notre objectif est d'utiliser Context pour basculer les classNames Image.jsde Dayà Night, en fonction de l'image que nous voulons rendre. Pour ce faire, nous ajoutons une propriété statique à notre composant appelé ContextType, puis nous utilisons une interpolation de chaîne pour l'ajouter aux classNames du composant.

Maintenant, les classNames contiennent la chaîne de valueprop. Remarque: j'ai déplacé ThemeContextdans son propre fichier pour éviter un bogue.

import React from "react"; import Button from "./Button"; import ThemeContext from "./themeContext"; class Image extends React.Component { render() { const theme = this.context; return ( ); } } Image.contextType = ThemeContext; export default Image; 

Contexte Consommateur

Malheureusement, cette approche ne fonctionne qu'avec des composants basés sur les classes. Si vous avez déjà entendu parler des Hooks dans React, vous saurez que nous pouvons faire à peu près tout avec des composants fonctionnels de nos jours. Donc, pour faire bonne mesure, nous devrions convertir nos composants en composants fonctionnels, puis utiliser un ThemeContext.Consumercomposant pour transmettre des informations via l'application.

Cela se fait en enveloppant nos éléments dans une instance de et à l'intérieur de celui-ci (où childrenaller), en fournissant une fonction qui retourne les éléments. Cela utilise le modèle "render prop" où nous fournissons une fonction régulière en tant qu'enfant qui renvoie du JSX à rendre.

import React from "react"; import Button from "./Button"; import ThemeContext from "./themeContext"; function Image(props) { // We don't need this anymore // const theme = this.context return (  {theme => ( )}  ); } // We don't need this anymore // Image.contextType = ThemeContext; export default Image; 

Remarque: Nous devons également envelopper le composant - cela nous permet d'ajouter des fonctionnalités au bouton plus tard.

import React from "react"; import ThemeContext from "./themeContext"; function Button(props) { return (  {context => (  Switch  ?   ?   )}  ); } export default Button; 

Extraire le fournisseur de contexte

Nous transmettons actuellement une valeur codée en dur via le fournisseur, cependant, notre objectif est de basculer entre la nuit et le jour avec notre bouton.

Cela nécessite de déplacer notre fournisseur vers un fichier séparé et de le placer dans son propre composant, dans ce cas, appelé ThemeContextProvider.

import React, { Component } from "react"; const { Provider, Consumer } = React.createContext(); class ThemeContextProvider extends Component { render() { return {this.props.children}; } } export { ThemeContextProvider, Consumer as ThemeContextConsumer }; 

Remarque: la propriété value est maintenant gérée dans le nouveau fichier ThemeContext.js et doit donc être supprimée de index.js.

Changement de contexte

Pour câbler le bouton, nous ajoutons d'abord l'état à ThemeContextProvider:

import React, { Component } from "react"; const { Provider, Consumer } = React.createContext(); // Note: You could also use hooks to provide state and convert this into a functional component. class ThemeContextProvider extends Component { state = { theme: "Day" }; render() { return {this.props.children}; } } export { ThemeContextProvider, Consumer as ThemeContextConsumer }; 

Ensuite, nous ajoutons une méthode pour basculer entre le jour et la nuit:

toggleTheme = () => { this.setState(prevState => { return { theme: prevState.theme === "Day" ? "Night" : "Day" }; }); }; 

Maintenant, nous changeons notre valuepropriété pour this.state.themequ'elle renvoie les informations de l'état.

 render() { return {this.props.children}; } } 

Next, we change value to an object containing {theme: this.state.theme, toggleTheme: this.toggleTheme}, and update all the places where we use a single value to look for theme in an object. This means that every theme becomes context and every reference to theme as value becomes context.theme.

Finally, we tell the button to listen for the onClick event and then fire context.toggleTheme - this updates the Consumers which are using the state from the Provider. The code for the button looks like this:

import React from "react"; import { ThemeContextConsumer } from "./themeContext"; function Button(props) { return (  {context => (  Switch  ?   ?   )}  ); } export default Button; 

Our button now switches the image between night and day in one click!

Context caveats

Like all good things in code, there are some caveats to using Context:

  • Don't use Context to avoid drilling props down just one or two layers. Context is great for managing state which is needed by large portions of an application. However, prop drilling is faster if you are just passing info down a couple of layers.

  • Avoid using Context to save state that should be kept locally. So if you need to save a user's form inputs, for example, use local state and not Context.

  • Always wrap the Provider around the lowest possible common parent in the tree - not the app's highest-level component. No need for overkill.

  • Lastly, if you pass an object as your value prop, monitor performance and refactor as necessary. This probably won't be needed unless a drop in performance is noticeable.

Wrap up

Cet exemple est assez simple et il serait probablement plus facile de mettre l'état dans l'application et de le transmettre via des accessoires. Cependant, nous espérons que cela montre le pouvoir d'avoir des consommateurs qui peuvent accéder aux données indépendamment des composants au-dessus d'eux dans l'arborescence.

Pour en savoir plus sur React Context et d'autres fonctionnalités intéressantes de React, vous pouvez rejoindre la liste d'attente de mon prochain cours avancé React. Ou si vous recherchez un cours plus convivial pour les débutants, vous pouvez consulter mon cours d'introduction gratuit sur React.

Bon codage :)