codelynx.dev
🇫🇷🇬🇧

Retour 24/10/2024

Redux est mort. Utilise Zustand à la place...

Écris par Melvyn Malherbe le 24/10/2024


Redux est mort. Certes, il est encore beaucoup utilisé mais pour des nouveaux projets je le déconseille, surtout avec la nouvelle manière de faire.

La solution maintenant se compose en deux librairies puissantes :

  1. Tanstack Query qui permet de gérer le server-state
  2. Zustand qui permet de gérer le client-state

Surtout que la majorité des états est maintenant stockée dans les server-components et n'a même plus lieu d'être dans le front-end.

Pourquoi Redux est mort ?

Redux a été la première librairie de state management vraiment populaire, s'il l'a été c'est car à l'époque le state en React n'était pas facile à gérer.

Redux a été pour des applications aux niveaux de Meta ADS avec des milliers de menus, sous-menus et appels API de tous les côtés.

Le state dans Meta est très compliqué à gérer et à maintenir.

Redux permet d'ajouter des states, qui sont gérés en "flux" et qui permet à chaque partie de l'application de définir leur "reducer" qui permettra de communiquer avec les autres parties de l'application.

Redux a été une révolution pour :

  • gérer le state d'applications complexes
  • travailler en équipe sans se marcher sur les pieds

Mais maintenant il est utilisé par des équipes de 3 développeurs sur des e-commerce, tu commences à voir le problème.

Les Server Components

La nouvelle philosophie de React qui pousse vers les Server Components vient réduire énormément le besoin d'un state manager aussi complexe.

La majorité des données ne sont plus stockées côté client, quand tu vois ce code :

TSX
export default async function ProductPage() {
  const products = await prisma.product.findMany();

  return (
    <ul>
      {products.map((product) => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
}

Ici, dans ce Server Component, il n'y a aucun client. Redux ne pourrait même pas exister. Il n'y a tout simplement pas de state, on vient juste afficher une liste de produits.

Mais à l'époque il aurait fallu faire un useEffect pour récupérer les données et les stocker dans le state.

En résumé, les Server Components changent beaucoup de paradigmes et réduisent encore plus le besoin d'un state manager aussi complexe.

Server-state

Cependant, parfois il faut être capable de venir stocker le Server State, c'est-à-dire le state de notre serveur.

Pour ça, Tanstack Query s'est imposé comme un leader incontournable.

Il va venir gérer un "cache" de toutes tes données et va te permettre de mettre à jour ton Server State quand tu veux.

TSX
'use client';

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useState } from 'react';

export const ProductList = () => {
  const queryClient = useQueryClient();

  const {
    data: products,
    error,
    isLoading,
  } = useQuery({

    queryKey: ['products'], 
    queryFn: async () => {

      // get call
    }, 
  });
  const mutation = useMutation({

    mutationFn: async (newProduct) => {

      // fetch call
    }, 
    onSuccess: () => {

      queryClient.invalidateQueries(['products']); 
    }, 
  }); 

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <ul>
        {products.map((product) => (
          <li key={product.id}>{product.name}</li>
        ))}
      </ul>
      <button onClick={handleAddProduct}>Add Product</button>
    </div>
  );
};

Ici, on peut facilement récupérer des données et les muter, c'est simple, efficace et fait pour ça.

Tanstack Query nous permet de gérer tout le Server State qui dépend de données asynchrones pour fonctionner.

Mais parfois, il y a des choses client. Par exemple, l'état actuel d'une Sidebar.

Ici quand on parle de Server-state ou Client-state, il faut comprendre que tout ici est stocké côté client. On parle plutôt des données qu'il contient. Le Server-state contient des données du Server alors que le Client-state contient des données du Client.

Client-state

Pour le client State, le leader c'est Zustand qui va te permettre de créer des stores, qui remplaceraient un useContext placé dans le App.tsx.

Tu peux créer facilement un store :

TSX
import { create } from 'zustand';

const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}));

Et là, on peut facilement utiliser notre store :

TSX
import { useStore } from './store';

export const Counter = () => {
  const { count, increment } = useStore();

  return (
    <div>
      <p>Current count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

Ce store, est accessible partout dans ton application, même en dehors de React :

TSX
import { useStore } from './store';

// Possible de l'utiliser en dehors de React
const increment = () => {
  useStore.getState().increment();
};

Zustand, contrairement à Redux, a une approche "micro" des stores. Il n'y a pas de reducers, il n'y a pas de dispatch et il n'y a pas d'action.

On va plutôt créer plein de stores, dans une application tu pourrais avoir :

  • useSidebarStore pour gérer l'état de la sidebar
  • useEditorStore pour gérer l'état de l'éditeur
  • etc...

Un store = une fonctionnalité.

Pourquoi ne pas utiliser useContext ? Déjà car tu vas avoir plus de code. Mais aussi car Zustand supporte les sélecteurs qui te permettent d'optimiser les renders.

Quand un contexte change, tous les composants qui le consomment sont re-rendus même ceux qui n'utilisent pas les données modifiées.

Alors qu'avec zustand il est possible de sélectionner les données :

TSX
import { useStore } from './store';

export const CounterIncrement = () => {
  const count = useStore((state) => state.increment);

  return (
    <div>
      <button onClick={count}>Increment</button>
    </div>
  );
};

Ce composant ne sera jamais re-rendu car la méthode increment ne va jamais changer (normalement).

Quand utiliser Redux ?

Redux est mort dans la grande majorité des applications. Si ton application dépend beaucoup de données côté serveur :

  • utilise les Server Components
  • utilise Tanstack Query

Si ton application a besoin d'un peu de données côté client :

  • utilise Zustand

Mais dans le rare cas où tu crées une application aussi complexe que Meta ADS, ou un manager de tickets où énormément de données ont un rapport entre elles et que c'est un joyeux bordel... déjà bonne chance.

Mais aussi ici, dans ce rare cas qui représente 5% des applications, utilise Redux.

Conclusion

Redux est presque mort... enfin pour la majorité des applications. Je t'ai partagé mes conseils à toi de les suivre.

Tu peux apprendre à mieux utiliser React et Zustand dans ma formation BegiNReact :

Le meilleur moyen d'apprendre React !

Rejoins par développeurs, cette formation reçoit une note de 4.7 / 5 🚀

Reçois 12 leçons premium pour maîtriser React et faire partie des meilleurs

Tu pourrais vouloir aussi apprendre pourquoi tu n'as pas besoin de useCallback ou la différence entre une propre et un state en React.

BeginReact

Cours React gratuit

Accède à des exercices, des vidéos et bien plus sur React dans la formation "BeginReact" 👇