On a vu dans un chapitre précédent qu'on pouvait faire descendre ou remonter de l'information au travers des propriétés de nos composant. Dans le cadre d'une application réelle cette manière de transférer l'information va s'avérer limitante avec souvent un grand nombre de composant à traverser. Pour remédier à ce problème il est possible d'utiliser un contexte qui va permettre d'exposer un état à un ensemble de composant enfant, sans avoir à faire transiter l'information dans l'ensemble de l'arbre.
Un contexte peut être créé via la méthode createContext()
qui prendra en paramètre une valeur de base qui sera utilisé si aucun contexte n'est fournit plus tard.
const TodoContext = createContext({todos: []})
Ensuite, n'importe quel composant peut récupérer la valeur dans le contexte à l'aide du hook useContext()
.
function Footer () {
const {todos} = useContext(TodoContext)
return <footer>
Il y a {todos.length} tâches
</footer>
}
Il est ensuite possible de définir un contexte pour toute une partie de l'application à l'aide d'un provider.
<TodoContext.Provider value={{todos: ['Tâche 1', 'Tâche 2']}}>
<TaskList/>
<Footer/>
</TodoContext.Provider>
Tous les composant enfant d'un provider, lorsqu'ils utilisent useContext()
, récupèrerons alors la valeur fournie par le provider. Il est aussi possible de créer un provider personnalisé pour par exemple exposé la fonction de mise à jour de l'état.
function TodosProvider ({children}) {
const [state, dispatch] = useReducer(reducer, {todos: []})
return <TodoContext.Provider value={{todos: state.todos, dispatch}}>
{children}
</TodoContext.Provider>
}
Ensuite ce provider peut être utilisé pour entourer notre application.
<TodosProvider>
<App />
</TodosProvider>
Ce qui permet aux composants de pouvoir d'interagir avec les données, peu importe leur position dans l'arbre.
function AddTodoButton () {
const {dispatch} = useContext(TodoContext)
return <button
onClick={dispatch({type: 'ADD_TODO', text: 'Ma nouvelle tâche'})}>
Ajouter
</button>
}
Pour plus d'exemples, n'hésitez pas à vous rendre sur la documentation de useReducer et pour un cas plus complexe n'hésitez pas à lire cet article.