Εισαγωγή στα thunks στο Redux
Στο προηγούμενο κεφάλαιο οργανώσαμε τη λειτουργία
του διακομιστή, της βάσης δεδομένων και του client για
ανταλλαγή δεδομένων. Τώρα πρέπει να
φτιάξουμε την τελευταία γέφυρα, που θα βοηθήσει
την 'σύγχρονη' οργανωμένη εφαρμογή μας Redux
να αλληλεπιδρά με τον ασύγχρονο
client, που δημιουργήσαμε στο τελευταίο
μάθημα του προηγούμενου κεφαλαίου, για να στέλνει
αιτήματα και να λαμβάνει τα απαραίτητα δεδομένα στην απάντηση.
Όπως θυμόμαστε από τα πρώτα μαθήματα της προηγούμενης
ενότητας, το Redux δεν γνωρίζει τίποτα για την εργασία με
ασύγχρονη λογική και για αυτό θα
χρησιμοποιήσουμε το thunk middleware. Αυτό το middleware
επιτρέπει την εργασία με τα αποσταλμένα actions,
τη χρήση στον κώδικα του thunk μας των μεθόδων dispatch και
getState του store, και επίσης βοηθά
τη μέθοδο dispatch να λειτουργεί όχι μόνο με
συνηθισμένα JS αντικείμενα, αλλά και με οντότητες,
όπως συναρτήσεις και promises.
Συνήθως η thunk-συνάρτηση καλείται με δύο
ορίσματα dispatch και getState
(αν χρειάζεται), που μπορούν να χρησιμοποιηθούν
στο σώμα αυτής της συνάρτησης. Με τη βοήθειά της μπορούν να
σταλούν συνηθισμένα actions. Επίσης
μπορεί να σταλεί μέσω store.dispatch.
Παράδειγμα μιας τέτοιας συνάρτησης φαίνεται παρακάτω:
const changeColorThunk = (dispatch, getState) => {
const colorBefore = getState()
console.log(`Παλιό Χρώμα: ${colorBefore.color}`)
dispatch(changeColor())
const colorAfter = getState()
console.log(`Νέο Χρώμα: ${colorAfter.color}`)
}
store.dispatch(changeColorThunk)
Ας ανοίξουμε τώρα την εφαρμογή μας με τα
προϊόντα. Το πρώτο πράγμα που πρέπει να λάβουμε
από το διακομιστή κατά την εκκίνηση της εφαρμογής - είναι
η λίστα των προϊόντων. Εφόσον συνήθως τα thunks
γράφονται στα slice αρχεία, θα ανοίξουμε το αρχείο
productsSlice.js.
Η καλή νέα είναι ότι
δεν χρειάζεται να ασχοληθούμε με την εγκατάσταση του Redux Thunk,
καθώς η συνάρτηση configureStore από το RTK
ήδη το κάνει αυτό για εμάς. Επομένως απλά θα προσθέσουμε
το createAsyncThunk στην εισαγωγή στο αρχείο:
import { createSlice, nanoid, createAsyncThunk } from '@reduxjs/toolkit'
Θα προσθέσουμε επίσης στην εισαγωγή και τον client μας:
import { client } from '../../api/client'
Και τώρα με τη βοήθεια του createAsyncThunk
θα δημιουργήσουμε το πρώτο μας thunk για την λήψη
προϊόντων, θα το κάνουμε αμέσως μετά
τη δήλωση του αντικειμένου initialState:
export const fetchProducts = createAsyncThunk()
Πρώτη παράμετρος του createAsyncThunk θα
παίρνει μια συμβολοσειρά για τον τύπο του generated
action, και δεύτερη - τη συνάρτηση callback για
το payload, που στο αποτέλεσμα θα επιστρέψει
είτε δεδομένα, είτε promise με σφάλμα (δείτε
το αρχείο client.js). Στον κώδικα της συνάρτησης
καλούμε το client.get και του περνάμε τη διαδρομή,
που ορίσαμε στο διακομιστή (δείτε
τις παραμέτρους που δέχεται το http.get στο
server.js):
export const fetchProducts = createAsyncThunk(
'products/fetchProducts',
async () => {
const response = await client.get('/fakeServer/products')
return response.data
}
)
Ανοίξτε την εφαρμογή σας με τους μαθητές.
Ανοίξτε σε αυτή το αρχείο studentsSlice.js.
Εισάγετε σε αυτό τη συνάρτηση createAsyncThunk
για τη δημιουργία thunk, και επίσης το client για
την αποστολή API αιτημάτων στο διακομιστή.
Αμέσως μετά τη δήλωση του αντικειμένου initialState
με τη βοήθεια του createAsyncThunk δημιουργήστε ένα thunk
fetchStudents για τη λήψη της λίστας μαθητών,
που θα στέλνει GET-αίτημα στη
διεύθυνση /fakeServer/students, που ορίσατε
σας στο αρχείο server.js, και να επιστρέφει
response.data, όπως φαίνεται στο υλικό
του μαθήματος. Ως πρώτη παράμετρο για
το createAsyncThunk ορίστε τη συμβολοσειρά
students/fetchStudents για τον τύπο του action.