Ecrit par Nathanaël Cherrier

Mettre à jour un contexte React depuis son consumer

Publié dans ,

Partagez l'article

twitter facebook

Parmi les dernières nouveautés de ReactJS qui ont grandement améliorées le DX (Developer eXperience) du framework, il y a le Context API et les hooks. Dans cet article, nous nous intéresserons au Context API.

Je ne vais pas expliquer dans le détail comment fonctionne le Context API dans cet article. Si vous ne savez pas de quoi il s'agit, je vous invite à lire rapidement la très bonne documentation de React à ce sujet.

Merci à @alexislepresle pour son idée d'article ! Vous pouvez, vous aussi, contribuer au blog en demandant un sujet en particulier depuis le forum.

Comment modifier un contexte depuis un de ses enfants ?

Pour rappel, le Context API permet de stocker des données et de les rendre accessibles à n'importe quel enfant qui souhaite l'utiliser. Cela est valide quelque soit le niveau de l'enfant dans la hiérarchie des composants.

const MyContext = React.createContext()

const MyComponent = () => {
    const count = useContext(MyContext)
    
    return (
        <div>price: {count}</div>
	)
}

const App = () => (
    <MyContext.Provider value={2}>
    	<div>
    		<MyComponent />
		    <MyComponent />
    	</div>
    </MyContext.Provider>
)

Si on simplifie au maximum, les contextes sont fait pour faire passer de l'information du haut vers le bas de l'arbre des composants. Comment pourrait-on faire aller de l'information dans le sens inverse ? Ou juste modifier le contexte sans même remonter de l'information ?

En utilisant les fonctions, les closures. Comme ce sont de simples valeurs comme les autres, vous pouvez stocker des fonctions dans votre contexte. Si vous stockez une fonction qui est capable de modifier le contenu du contexte, tous les enfants de celui-ci pourront l'utiliser et donc le modifier.

Pour rendre les valeurs du contexte facilement modifiables, je vais utiliser le passage par référence de JavaScript (inspiré du C, bien-sûr).

const MyContext = React.createContext()

const MyComponent = () => {
    const { count } = useContext(MyContext)
    
    return (
        <div>price: {count}</div>
	)
}

const App = () => {
    const [count] = useState(0)
    
    return (
	    <MyContext.Provider value={{ count }}>
    		<div>
    			<MyComponent />
		    	<MyComponent />
    		</div>
    	</MyContext.Provider>
	)
}

Avec le code précédent, nous obtenons le même résultat. Nous avons simplement déplacé le stockage des données vers le state du composant parent.

Il nous suffit maintenant d'ajouter une fonction qui modifie ce state pour pouvoir appliquer la modification depuis un enfant.

const MyContext = React.createContext()

const MyComponent = () => {
    const { count, increment } = useContext(MyContext)
    
    return (
        <div onClick={increment}>price: {count}</div>
	)
}

const App = () => {
    const [count, updateCount] = useState(0)
    function increment() {
        updateCount(count + 1)
    }
    
    return (
	    <MyContext.Provider value={{ count, increment }}>
    		<div>
    			<MyComponent />
		    	<MyComponent />
    		</div>
    	</MyContext.Provider>
	)
}

Maintenant lorsque l'utilisateur clique sur le prix, celui-ci augment de 1 à chaque fois.

Pour résumé, dans le composant où nous voulons utiliser le contexte, nous stockons les données dans le state de ce composant et nous créons une fonction capable de modifier ce state. Ensuite, nous pouvons passer le state et la fonction comme valeur du contexte.

Il devient alors possible depuis l'enfant de récupérer la fonction de modification et de l'utiliser pour mettre à jour le contexte.


Pour aller plus loin:


Si vous avez des questions ou des remarques/conseils, n'hésitez pas à en discuter avec les autres membres du forum (zone de commentaires plus bas)! Et si vous aimez l'article, n'oubliez pas de le partager avec vos amis. Vous pouvez aussi soutenir le blog sur Patreon.