Réducteurs supplémentaires dans Redux
Ouvrons notre application avec les produits,
et dans celle-ci le fichier productsSlice.js. Vous avez probablement
remarqué que nous avons créé le thunk fetchProducts
comme une fonction séparée ? Nous l'avons fait ainsi,
parce que createSlice ne prend pas en charge la définition
de thunks. Comment dans ce cas pouvons-nous faire
que le réducteur du slice products réagisse aux actions
qui sont définies en dehors de products ?
Après tout, nous avons justement besoin de traiter les actions
envoyées par le thunk fetchProducts.
Pour de tels cas, createSlice possède
une propriété extraReducers, qui permet
d'ajouter des réducteurs supplémentaires, qui
à leur tour traiteront les actions
définies non pas dans ce slice.
Maintenant, dans le corps de la fonction createSlice
après la propriété reducers avec tous les réducteurs
ajoutons une autre méthode extraReducers :
extraReducers() {},
Nous devons passer à cette méthode un objet
builder, qui possède des méthodes, avec
lesquelles on peut ajouter
des réducteurs supplémentaires :
extraReducers(builder) {},
Nous allons utiliser une des méthodes de builder -
addCase, qui prend en premier paramètre un
action creator, et en second un réducteur. Une des
actions qui nous sera envoyée par
fetchProducts lors de la requête est
fetchProducts.pending, ce qui nous indique
que la requête a été envoyée. Dans ce
cas, changeons le statut en 'in progress'
(auparavant il était 'idle') :
extraReducers(builder) {
builder.addCase(fetchProducts.pending, (state) => {
state.status = 'in progress'
})
},
Maintenant, traitons l'action qui sera envoyée
en cas de requête réussie. Ici, nous
changerons non seulement le statut dans le state en
'success', mais nous récupérerons aussi les produits dans
le slice products à partir du payload de l'action.
Pour rassembler tous les produits, nous aurons besoin de
la méthode concat :
extraReducers(builder) {
builder
.addCase(fetchProducts.pending, (state) => {
state.status = 'in progress'
})
.addCase(fetchProducts.fulfilled, (state, action) => {
state.status = 'success'
state.products = state.products.concat(action.payload)
})
},
En cas de requête échouée, nous changerons le
statut en 'fail' et enregistrerons dans le state
le message d'erreur :
.addCase(fetchProducts.rejected, (state, action) => {
state.status = 'fail'
state.error = action.error.message
})
Si nous lançons maintenant notre application
et cliquons dans le menu sur 'Products', alors
après quelques secondes (vous vous souvenez du délai,
que nous avons mis sur le serveur ?) nous verrons
la liste des produits.
De la même manière, nous verrons les changements dans les Redux
DevTools. Maintenant, nos produits apparaîtront aussi
dans le state (regardez l'onglet 'State'),
si vous avez cliqué sur l'action
products/fetchProducts/fulfilled.
Le nouveau statut 'success' y apparaîtra aussi.
Cliquez maintenant sur l'action
products/fetchProducts/pending et regardez
ce qui diffère maintenant dans l'onglet 'State'.
Le seul moment désagréable qui
peut vous arriver (j'en ai parlé
dans la leçon précédente) - c'est la duplication
de la requête de données. En conséquence, dans notre
liste nous n'aurons pas 8, mais pas moins de
16 produits et des avertissements critiques
dans la console du développeur. Réglons
cela dans la prochaine leçon.
Ouvrez votre application avec les étudiants.
Ouvrez-y le fichier studentsSlice.js. Dans
le corps de la fonction createSlice après la propriété
reducers ajoutez la propriété extraReducers.
Passez à la méthode extraReducers le builder.
À l'aide de la méthode builder.addCase
ajoutez le traitement pour les actions pending,
fulfilled et rejected, qui
sont envoyées par fetchStudents lors de la requête
de données, comme montré dans la leçon.