## Introduction à Redux Toolkit
La gestion de l'état est l'un des défis majeurs dans les applications React. Redux est une solution populaire pour gérer l'état global, mais sa configuration traditionnelle peut être verbeuse. Redux Toolkit (RTK) a été créé pour simplifier l'utilisation de Redux et suivre les meilleures pratiques.
## Pourquoi utiliser Redux Toolkit ?
Redux Toolkit offre plusieurs avantages par rapport à Redux classique :
- **Configuration simplifiée** : Moins de boilerplate code - **Immer intégré** : Écrire des reducers comme si vous modifiez directement l'état - **RTK Query** : Solution intégrée pour gérer les données distantes - **Dev tools inclus** : Configuration automatique des Redux DevTools
## Installation
```bash npm install @reduxjs/toolkit react-redux ```
## Configuration du store
Voici comment configurer un store Redux avec Redux Toolkit :
```jsx // store.js import { configureStore } from '@reduxjs/toolkit'; import counterReducer from './features/counter/counterSlice'; import todosReducer from './features/todos/todosSlice';
export const store = configureStore({ reducer: { counter: counterReducer, todos: todosReducer, }, }); ```
## Création d'un slice
Un "slice" dans Redux Toolkit est un ensemble de reducers et d'actions pour une fonctionnalité spécifique :
```jsx // features/counter/counterSlice.js import { createSlice } from '@reduxjs/toolkit';
const initialState = { value: 0, };
export const counterSlice = createSlice({ name: 'counter', initialState, reducers: { increment: (state) => { // Immer nous permet d'écrire du code "mutant" // qui sera transformé en code immuable state.value += 1; }, decrement: (state) => { state.value -= 1; }, incrementByAmount: (state, action) => { state.value += action.payload; }, }, });
// Les actions sont générées automatiquement export const { increment, decrement, incrementByAmount } = counterSlice.actions;
// Sélecteur pour accéder à l'état export const selectCount = (state) => state.counter.value;
export default counterSlice.reducer; ```
## Utilisation dans un composant
```jsx // features/counter/Counter.jsx import React from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { increment, decrement, selectCount } from './counterSlice';
export function Counter() { const count = useSelector(selectCount); const dispatch = useDispatch();
return ( <div> <div> <button aria-label="Decrement value" onClick={() => dispatch(decrement())} > - </button> <span>{count}</span> <button aria-label="Increment value" onClick={() => dispatch(increment())} > + </button> </div> </div> ); } ```
## Thunks pour la logique asynchrone
Redux Toolkit facilite également la gestion des actions asynchrones avec les thunks :
```jsx // features/counter/counterSlice.js (suite) import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
// Thunk asynchrone export const incrementAsync = createAsyncThunk( 'counter/incrementAsync', async (amount) => { // Simuler une API await new Promise((resolve) => setTimeout(resolve, 1000)); return amount; } );
const counterSlice = createSlice({ name: 'counter', initialState, reducers: { // ... reducers synchrones }, extraReducers: (builder) => { builder .addCase(incrementAsync.pending, (state) => { state.status = 'loading'; }) .addCase(incrementAsync.fulfilled, (state, action) => { state.status = 'idle'; state.value += action.payload; }) .addCase(incrementAsync.rejected, (state) => { state.status = 'failed'; }); }, }); ```
## RTK Query pour les API
Redux Toolkit inclut RTK Query, une puissante solution pour gérer les interactions avec les API :
```jsx // api/apiSlice.js import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const apiSlice = createApi({ reducerPath: 'api', baseQuery: fetchBaseQuery({ baseUrl: '/api' }), tagTypes: ['Todos'], endpoints: (builder) => ({ getTodos: builder.query({ query: () => '/todos', providesTags: ['Todos'], }), addTodo: builder.mutation({ query: (todo) => ({ url: '/todos', method: 'POST', body: todo, }), invalidatesTags: ['Todos'], }), }), });
export const { useGetTodosQuery, useAddTodoMutation } = apiSlice; ```
Utilisation dans un composant :
```jsx import React from 'react'; import { useGetTodosQuery, useAddTodoMutation } from './apiSlice';
function TodoList() { const { data: todos, isLoading } = useGetTodosQuery(); const [addTodo] = useAddTodoMutation();
if (isLoading) return <div>Loading...</div>;
return ( <div> <button onClick={() => addTodo({ text: 'New Todo' })}>Add Todo</button> <ul> {todos.map((todo) => ( <li key={todo.id}>{todo.text}</li> ))} </ul> </div> ); } ```
## Bonnes pratiques avec Redux Toolkit
1. **Organisez par fonctionnalité** : Structurez votre code par fonctionnalité (slices) plutôt que par type (actions, reducers, etc.).
2. **Utilisez les selectors** : Créez des selecteurs pour accéder à l'état et composez-les pour des données dérivées.
3. **Normalisez les données complexes** : Utilisez `createEntityAdapter` pour gérer efficacement les collections d'objets.
4. **Préférez RTK Query pour les API** : Plutôt que d'écrire vos propres thunks pour les appels API, utilisez RTK Query.
## Conclusion
Redux Toolkit simplifie considérablement l'utilisation de Redux et encourage les bonnes pratiques. Si vous trouviez Redux trop verbeux ou complexe, RTK vaut vraiment la peine d'être essayé.
Avec ses fonctionnalités comme les slices, les thunks intégrés et RTK Query, Redux Toolkit offre une solution complète pour la gestion de l'état global dans les applications React.