Pourquoi Zustand avec React : guide complet ?
Contexte réel : pourquoi un dev a besoin de ça au quotidien
Au fil des années, les applications web ont évolué en devenir plus complexes et interactives. La gestion du state (l'état) dans ces applications a toujours été un défi majeur pour les développeurs. Les contextes profonds, les composants réutilisables et les besoins croissants en performance ont conduit à la création d'outils comme Zustand, qui simplifie significativement cette gestion.
Un cas d'utilisation concret en 2-3 phrases
Imaginez une application de gestion des tâches où chaque utilisateur peut avoir sa propre liste de tâches et des sous-listes. Chaque tâche doit pouvoir être marquée comme terminée, modifiée ou supprimée. Avec Zustand, on peut facilement gérer ce state global tout en maintenant une structure de code claire et maintenable.
Prerequis
- Connaissance de base de React
- Compréhension des concepts de composants fonctionnels
- Familiarité avec les hooks (useState, useEffect)
- Node.js installé (v14+ recommandé)
Concepts fondamentaux
Zustand : un hook simple pour gérer le state global
Zustand est un petit butin JavaScript permettant d'ajouter une gestion de state globale à vos applications React. Il utilise des hooks et n'a pas besoin d'installeur.
// Installer Zustand si vous n'avez pas encore installé
npm install zustand
Création d'un store
Un store est un conteneur qui stocke le state de votre application. Vous pouvez en créer un avec une simple fonction.
import create from 'zustand';
const useStore = create((set) => ({
tasks: [],
addTask: (task) => set((state) => ({ tasks: [...state.tasks, task] })),
removeTask: (id) => set((state) => ({ tasks: state.tasks.filter(task => task.id !== id) }))
}));
Utilisation du store dans un composant
Maintenant que nous avons créé notre store, nous pouvons l'utiliser dans un composant React.
import { useStore } from './store';
const TaskList = () => {
const tasks = useStore((state) => state.tasks);
const addTask = useStore((state) => state.addTask);
return (
<div>
<h1>Task List</h1>
<ul>
{tasks.map(task => (
<li key={task.id}>{task.text}</li>
))}
</ul>
<button onClick={() => addTask({ id: Date.now(), text: 'New Task' })}>Add Task</button>
</div>
);
};
Mise en pratique : projet fil rouge
Objectif du projet
Construire un gestionnaire de tâches simple avec Zustand. L'utilisateur devra pouvoir ajouter, modifier et supprimer des tâches.
Étapes
Initialiser le projet
npx create-react-app task-manager-zustand cd task-manager-zustandInstaller Zustand
npm install zustandCréer le store
Créez un fichier
store.jsdans le répertoire racine.import create from 'zustand'; const useStore = create((set) => ({ tasks: [], addTask: (task) => set((state) => ({ tasks: [...state.tasks, task] })), removeTask: (id) => set((state) => ({ tasks: state.tasks.filter(task => task.id !== id) })) })); export default useStore;Créer le composant
TaskListCréez un fichier
TaskList.jsdans le répertoiresrc.import React, { useState } from 'react'; import useStore from './store'; const TaskList = () => { const tasks = useStore((state) => state.tasks); const addTask = useStore((state) => state.addTask); const removeTask = useStore((state) => state.removeTask); const [newTask, setNewTask] = useState(''); return ( <div> <h1>Task List</h1> <ul> {tasks.map(task => ( <li key={task.id}> {task.text} <button onClick={() => removeTask(task.id)}>Remove</button> </li> ))} </ul> <input type="text" value={newTask} onChange={(e) => setNewTask(e.target.value)} /> <button onClick={() => addTask({ id: Date.now(), text: newTask })}>Add Task</button> </div> ); }; export default TaskList;Utiliser le composant
TaskListModifiez
src/App.jspour inclureTaskList.import React from 'react'; import './App.css'; import TaskList from './TaskList'; function App() { return ( <div className="App"> <TaskList /> </div> ); } export default App;Lancer l'application
npm start
Code complet
Voici le code complet du projet :
// src/store.js
import create from 'zustand';
const useStore = create((set) => ({
tasks: [],
addTask: (task) => set((state) => ({ tasks: [...state.tasks, task] })),
removeTask: (id) => set((state) => ({ tasks: state.tasks.filter(task => task.id !== id) }))
}));
export default useStore;
// src/TaskList.js
import React, { useState } from 'react';
import useStore from './store';
const TaskList = () => {
const tasks = useStore((state) => state.tasks);
const addTask = useStore((state) => state.addTask);
const removeTask = useStore((state) => state.removeTask);
const [newTask, setNewTask] = useState('');
return (
<div>
<h1>Task List</h1>
<ul>
{tasks.map(task => (
<li key={task.id}>
{task.text}
<button onClick={() => removeTask(task.id)}>Remove</button>
</li>
))}
</ul>
<input
type="text"
value={newTask}
onChange={(e) => setNewTask(e.target.value)}
/>
<button onClick={() => addTask({ id: Date.now(), text: newTask })}>Add Task</button>
</div>
);
};
export default TaskList;
// src/App.js
import React from 'react';
import './App.css';
import TaskList from './TaskList';
function App() {
return (
<div className="App">
<TaskList />
</div>
);
}
export default App;
Erreurs fréquentes et debugging
1. Attempted to call a function on an object that was not a callable.
// ❌ Mauvais
useStore.getState().addTask({ id: Date.now(), text: 'New Task' });
// ✅ Correct
const addTask = useStore((state) => state.addTask);
addTask({ id: Date.now(), text: 'New Task' });
2. Error: Invalid hook call.
// ❌ Mauvais
useStore.getState().tasks;
// ✅ Correct
const tasks = useStore((state) => state.tasks);
3. ReferenceError: useStore is not defined
// ❌ Mauvais
import { useStore } from 'zustand';
// ✅ Correct
import useStore from './store';
Pour aller plus loin
Zustand avec TypeScript : Explorez comment utiliser Zustand en conjonction avec TypeScript pour une meilleure type-safety.
Persisting the State : Utilisez des bibliothèques comme
zustand-middleware-persistpour persister le state entre les sessions.Selectors and Derivatives : Découvrez comment utiliser les selectors et les derivatives pour optimiser la performance de votre application.
Défi pratique
Créez une application simple qui permet d'afficher une liste de livres avec des détails tels que l'auteur, le titre et la date de publication. Ajoutez la possibilité d'ajouter, modifier et supprimer des livres.