Πρόσθετοι Reducers στο Redux
Ας ανοίξουμε την εφαρμογή μας με τα προϊόντα,
και σε αυτή το αρχείο productsSlice.js. Πιθανότατα έχετε
παρατηρήσει ότι δημιουργήσαμε το thunk fetchProducts
ως ξεχωριστή συνάρτηση; Το κάναμε έτσι, γιατί
η createSlice δεν υποστηρίζει τον ορισμό
thunks. Πώς λοιπόν σε αυτή την περίπτωση μπορούμε να κάνουμε
τον reducer του slice products να ανταποκρίνεται σε actions,
που έχουν οριστεί εκτός του products;
Εξάλλου, χρειαζόμαστε ακριβώς να επεξεργαστούμε actions,
που στέλνει το thunk fetchProducts.
Για τέτοιες περιπτώσεις, η createSlice έχει
την ιδιότητα extraReducers, που επιτρέπει
την προσθήκη πρόσθετων reducers, οι οποίοι
με τη σειρά τους θα επεξεργάζονται actions,
που δεν έχουν οριστεί σε αυτό το slice.
Ας προσθέσουμε τώρα στο σώμα της συνάρτησης createSlice
μετά την ιδιότητα reducers με όλους τους reducers
ακόμη μια μέθοδο extraReducers:
extraReducers() {},
Σε αυτή τη μέθοδο πρέπει να περάσουμε ένα αντικείμενο
builder, που έχει μεθόδους, με τις
οποίες μπορούμε να προσθέσουμε
πρόσθετους reducers:
extraReducers(builder) {},
Θα χρησιμοποιήσουμε μια από τις μεθόδους του builder -
την addCase, που παίρνει ως πρώτη παράμετρο
ένα action creator, και ως δεύτερη ένα reducer. Ένα από
τα actions, που θα μας στέλνει
το fetchProducts κατά το αίτημα είναι
το fetchProducts.pending, που μας λέει
ότι το αίτημα στάλθηκε. Ας αλλάξουμε σε αυτή
την περίπτωση την κατάσταση σε 'in progress'
(πριν ήταν 'idle'):
extraReducers(builder) {
builder.addCase(fetchProducts.pending, (state) => {
state.status = 'in progress'
})
},
Τώρα ας επεξεργαστούμε το action, που θα σταλεί
σε περίπτωση επιτυχημένου αιτήματος. Εδώ θα
αλλάξουμε όχι μόνο την κατάσταση στο state σε
'success', αλλά και θα πάρουμε τα προϊόντα
στο slice products από το payload του action.
Για να συλλέξουμε όλα τα προϊόντα θα χρειαστούμε
τη μέθοδο 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)
})
},
Σε περίπτωση αποτυχημένου αιτήματος θα αλλάξουμε
την κατάσταση σε 'fail' και θα γράψουμε στο state
το μήνυμα σφάλματος:
.addCase(fetchProducts.rejected, (state, action) => {
state.status = 'fail'
state.error = action.error.message
})
Αν τώρα εκκινήσουμε την εφαρμογή μας
και στο μενού κλικάρουμε στο 'Products', τότε
μετά από μερικά δευτερόλεπτα (θυμάστε την καθυστέρηση,
που ορίσαμε στον server?) θα δούμε
τη λίστα με τα προϊόντα.
Με τον ίδιο τρόπο θα δούμε τις αλλαγές και στα Redux
DevTools. Τώρα τα προϊόντα μας θα εμφανιστούν
και στο state (κοιτάξτε την καρτέλα 'State'),
αν έχετε κλικάρει στο action
products/fetchProducts/fulfilled.
Εκεί θα εμφανιστεί και η νέα κατάσταση 'success'.
Κλικάρετε τώρα στο action
products/fetchProducts/pending και κοιτάξτε,
πως διαφέρει τώρα η καρτέλα 'State'.
Η μόνη δυσάρεστη στιγμή, που
μπορεί να σας συμβεί (το είπα γι' αυτό
στο προηγούμενο μάθημα) - είναι ο διπλασιασμός
του αιτήματος δεδομένων. Ως αποτέλεσμα, στη
λίστα μας θα έχουμε όχι 8, αλλά ολόκληρα
16 προϊόντα και κρίσιμα προειδοποιητικά
στο console του προγραμματιστή. Ας
ασχοληθούμε με αυτό στο επόμενο μάθημα.
Ανοίξτε την εφαρμογή σας με τους μαθητές.
Ανοίξτε σε αυτή το αρχείο studentsSlice.js. Στο
σώμα της συνάρτησης createSlice μετά την ιδιότητα
reducers προσθέστε την ιδιότητα extraReducers.
Περάστε στη μέθοδο extraReducers το builder.
Με τη βοήθεια της μεθόδου builder.addCase
προσθέστε επεξεργασία για τα actions pending,
fulfilled και rejected, που
στέλνει το fetchStudents κατά το αίτημα
δεδομένων, όπως φαίνεται στο μάθημα.