La question du state management React revient dans chaque projet. Redux a longtemps dominé, mais son verbosité a poussé l’écosystème vers des alternatives plus légères. En 2026, trois approches couvrent 95% des besoins.
Context API : pour le state partagé simple
La Context API est incluse dans React. Elle suffit pour des états globaux simples (thème, langue, utilisateur connecté) qui changent peu fréquemment.
const AuthContext = createContext<User | null>(null);
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null);
return (
<AuthContext.Provider value={user}>
{children}
</AuthContext.Provider>
);
}
// Dans un composant
const user = useContext(AuthContext);
Limitation : chaque mise à jour du contexte re-render tous les composants qui le consomment. Pour du state qui change fréquemment (ex : compteur, formulaire), c’est un problème de performances.
Zustand : la bibliothèque minimaliste
Zustand est devenu le choix par défaut pour le state management léger en dehors de Redux.
import { create } from 'zustand'
interface CartStore {
items: CartItem[];
addItem: (item: CartItem) => void;
removeItem: (id: string) => void;
total: () => number;
}
const useCartStore = create<CartStore>((set, get) => ({
items: [],
addItem: (item) => set((state) => ({
items: [...state.items, item]
})),
removeItem: (id) => set((state) => ({
items: state.items.filter(i => i.id !== id)
})),
total: () => get().items.reduce((sum, item) => sum + item.price, 0),
}));
// Dans un composant
const { items, addItem, total } = useCartStore();
Points forts : API simple, pas de boilerplate, DevTools disponibles, subscriptions sélectives (un composant ne re-render que si les données qu’il consomme changent).
Jotai : la gestion atomique
Jotai adopte une approche atomique inspirée de Recoil. Chaque morceau d’état est un “atom” indépendant.
import { atom, useAtom } from 'jotai'
const countAtom = atom(0)
const doubleCountAtom = atom((get) => get(countAtom) * 2)
function Counter() {
const [count, setCount] = useAtom(countAtom)
const [doubleCount] = useAtom(doubleCountAtom)
return <button onClick={() => setCount(c => c + 1)}>
{count} (double: {doubleCount})
</button>
}
Points forts : granularité fine, atoms dérivés, intégration naturelle avec React Suspense.
Tableau de décision
| Besoin | Solution recommandée |
|---|---|
| État partagé simple, peu de MAJ | Context API |
| State global avec logique métier | Zustand |
| State fragmenté, granularité fine | Jotai |
| Application très complexe, historique d’actions | Redux Toolkit |
Server State : TanStack Query
Séparez le server state (données issues d’API) du client state. TanStack Query (ex-React Query) gère le caching, la revalidation et les états de chargement/erreur nettement mieux que de le faire manuellement dans un store Zustand.
const { data: users, isLoading } = useQuery({
queryKey: ['users'],
queryFn: () => fetch('/api/users').then(r => r.json()),
staleTime: 5 * 60 * 1000, // 5 minutes
})
Notre formation React couvre ces patterns avec des projets pratiques complets.