Découvrez les avantages de Redux Toolkit
Enfin ! Nous l’avons déjà installé avec Redux, mais nous n’en avons pas encore parlé – c’est quoi Redux Toolkit ?
Redux Toolkit est une librairie qui facilite la gestion de l'état dans les applications React avec Redux. Développée pour rendre l'utilisation de Redux plus simple, plus concise et plus agréable, en fournissant des utilitaires prédéfinis pour certaines tâches courantes. Elle est suivie d’une documentation complète et d’un guide des meilleures pratiques afin de nous aider à intégrer Redux d’une façon plus conventionnelle.
Elle embarque aussi une bonne partie des modules complémentaires de Redux qui faciliteront le développement. Par exemple, la gestion du code asynchrone et le déclenchement automatique des actions en fonction du résultat de la promesse avec createAsyncThunk
. Ou bien, de pouvoir combiner la génération d’action, de reducers et de sélecteurs et de composer notre store par fonctionnalités grâce à createSlice
.
Ne vous inquiétez pas, on verra tout ça dans les chapitres suivants, ainsi que d’autres outils qui compléteront notre “kit”.
Enfin, Redux Toolkit est soutenu par la communauté Redux et dispose de tutoriels et d'exemples pour vous aider à démarrer rapidement, en plus de sa documentation solide.
Définissez vos actions avec createAction
Voyons tout de suite comment Redux Toolkit facilite la création de nos actions !
Dans nos précédents appels au dispatch
, nous avons écrit entièrement un objet de la forme suivante pour définir l’action :
{
type: "ACTION_NAME",
payload : {
...
}
}
Pour éviter de réécrire à chaque fois nos actions à dispatch, nous pouvons définir ce qu’on appelle des action creators. C’est-à-dire des fonctions qui vont nous retourner un objet, dont les propriétés correspondent à celles de l'action, et l’appeler comme ci-dessous :
const myAction = (payloadValue) => ({
type: "ACTION_NAME",
payload: payloadValue,
})
store.dispatch(myAction({/* payload */}))
Et si nous voulons pouvoir utiliser la même clé d’action pour notre reducer, nous devons exporter la clé comme ci-dessous :
export const MY_ACTION = "MY_ACTION"
const myAction = (payloadValue) => ({
type: MY_ACTION,
payload: payloadValue,
})
import { MY_ACTION } from "./actions"
const reducer = (state = initialState, action) => {
switch (action.type) {
case MY_ACTION:
return {
...state,
/* payload */
}
default:
return state
}
}
Redux Toolkit nous fournit un outil pour simplifier cela, createAction
.
createAction
renvoie un action creator
, et la variable créée peut être utilisée comme clé dans nos reducers.
On voit comment l’utiliser ci-dessous :
import { createAction } from '@reduxjs/toolkit'
export const myAction = createAction('MY_ACTION')
store.dispatch(myAction({/* payload */}))
Notez que createAction
peut prendre un deuxième paramètre qui permet de préparer le payload
associé à l’action. C’est très utile lorsque nous voulons nous assurer du format des données, par exemple. Ci-dessous, une petite démonstration :
export const addEvent = createAction('ADD_EVENT', (date) => ({
payload: {
day: date.getDate(),
month: date.getMonth(),
year: date.getFullYear(),
}
}))
store.dispatch(addEvent(new Date("2023-03-03")))
Via l'exemple ci-dessus, nous nous assurons que ce qui est passé en payload n'est pas une date JavaScript, mais directement un objet contenant explicitement le jour, le mois et l'année.
Définissez vos reducers avec createReducer
Nous venons de voir createAction
, voilà qui simplifie grandement la gestion des actions.
Mais quid de celle-ci dans nos reducers ? Aurions-nous une manière plus simple et plus esthétique de gérer nos actions dans nos reducers ?
Eh bien oui, grâce à createReducer
.
C’est une fonction qui nous permet de générer un reducer et d’y associer les différentes actions. Elle prend en paramètre l’état initial et une fonction qui va nous permettre d’ajouter chacun de nos cas. Ci-après, je vous montre comment l’utiliser dans des portions de code “démos” qui présentent la forme, et ne sont pas rattachées à notre projet fil rouge.
D’abord, en passant une fonction builder
:
import { createAction, createReducer } from '@reduxjs/toolkit'
export const myAction = createAction('MY_ACTION')
const initialState = {}
export const reducer = createReducer(initialState, function(builder) {
builder.addCase(myAction, (state, action) => {
/** RETURN NEW STATE VALUE */
})
})
On peut aussi bien définir nos actions en passant un objet en paramètre :
export const reducer = createReducer(initialState, {
[myAction]: (state, action) => ({
/** RETURN NEW STATE VALUE */
})
})
On peut donc très bien passer un objet pour configurer le reducer ou bien passer une fonction builder
, d’où les deux implémentations précédentes.
À vous de jouer !
On a vu comment manipuler les action creators et les ajouter à notre reducer.
Appliquons désormais cette nouvelle approche dans notre projet.
Nous avons 4 actions à remplacer dans notre reducer : ADD_PRODUCT
, REMOVE_PRODUCT
, APPLY_VOUCHER
et UPDATE_FIRSTNAME
.
Je vous propose donc de les remplacer par les actions addProduct
, removeProduct
, applyVoucher
et updateFirstName
.
Ci-dessous, vous trouverez ma solution :
En résumé
Redux Toolkit va nous guider dans la mise en place de notre store et va nous fournir un ensemble d’outils complémentaires.
Il est conçu pour être compatible avec des applications Redux existantes, permettant une migration progressive sans nécessité de réécrire entièrement le code.
Utiliser
createAction
nous permet d’avoir une définition claire de ce que le store permet comme action.Grâce à la combinaison de
createAction
et decreateReducer
, nous avons une syntaxe plus simple au niveau de notre reducer.
Maintenant que nous avons vu comment créer des actions via createAction
et comment les l’utiliser grâce à createReducer
, je vous propose de revenir sur l’organisation de notre fichier app/store.js
.