Wprowadzenie do thunks w Redux
W poprzednim rozdziale zorganizowaliśmy pracę
serwera, bazy danych i klienta dla
wymiany danych. Teraz musimy
zbudować ostatni most, który pomoże
naszej 'synchronicznej' zorganizowanej aplikacji Redux
współdziałać z asynchronicznym
klientem, którego stworzyliśmy na ostatniej
lekcji poprzedniego rozdziału, aby wysyłać
zapytania i otrzymywać potrzebne dane w odpowiedzi.
Jak pamiętamy z pierwszych lekcji poprzedniego
działu, Redux nie wie nic o pracy z
logiką asynchroniczną i w tym celu będziemy
używać thunk middleware. Ten middleware
pozwala pracować z wysłanymi actions,
używać w kodzie naszego thunk metod dispatch i
getState store, a także pomagać
metodzie dispatch pracować nie tylko z
zwykłymi obiektami JS, ale także z takimi encjami,
jak funkcje i promisy.
Zwykle funkcja thunk jest wywoływana z dwoma
argumentami dispatch i getState
(w razie potrzeby), którymi można się posługiwać
w ciele tej funkcji. Za jej pomocą można
wysyłać zwykłe akcje. Również
można ją wysyłać przez store.dispatch.
Przykład takiej funkcji przedstawiono poniżej:
const changeColorThunk = (dispatch, getState) => {
const colorBefore = getState()
console.log(`Stary kolor: ${colorBefore.color}`)
dispatch(changeColor())
const colorAfter = getState()
console.log(`Nowy kolor: ${colorAfter.color}`)
}
store.dispatch(changeColorThunk)
Otwórzmy teraz naszą aplikację z
produktami. Pierwsza rzecz, którą musimy otrzymać
od serwera przy uruchomieniu aplikacji - to
lista produktów. Ponieważ zwykle thunks
są pisane w plikach slice,
to otworzymy plik
productsSlice.js.
Radosna wiadomość jest taka, że
nie musimy bawić się z instalacją Redux Thunk,
ponieważ funkcja configureStore z RTK
już zrobi to za nas. Dlatego po prostu dodajmy
createAsyncThunk do importu w pliku:
import { createSlice, nanoid, createAsyncThunk } from '@reduxjs/toolkit'
Dodajmy także do importu naszego klienta:
import { client } from '../../api/client'
A teraz za pomocą createAsyncThunk
stworzymy nasz pierwszy thunk do pobrania
produktów, zrobimy to zaraz po
deklaracji obiektu initialState:
export const fetchProducts = createAsyncThunk()
Pierwszym parametrem createAsyncThunk będzie
przyjmować ciąg znaków dla typu generowanego
action, a drugim - funkcję zwrotną dla
payload, która w wyniku zwróci
albo dane, albo promis z błędem (spójrzcie
na plik client.js). W kodzie funkcji
wywołujemy client.get i przekazujemy mu ścieżkę,
którą wskazaliśmy na serwerze (spójrzcie
na przyjmowane parametry http.get w
server.js):
export const fetchProducts = createAsyncThunk(
'products/fetchProducts',
async () => {
const response = await client.get('/fakeServer/products')
return response.data
}
)
Otwórz twoją aplikację ze studentami.
Otwórz w niej plik studentsSlice.js.
Zaimportuj do niego funkcję createAsyncThunk
dla tworzenia thunk, a także client dla
wysyłania zapytań API do serwera.
Zaraz po deklaracji obiektu initialState
za pomocą createAsyncThunk stwórz thunk
fetchStudents do pobrania listy studentów,
który będzie wysyłał zapytanie GET
pod adres /fakeServer/students, wskazany
u ciebie w pliku server.js, i zwracać
response.data, jak pokazano w materiałach
lekcji. Jako pierwszy parametr dla
createAsyncThunk podaj ciąg znaków
students/fetchStudents dla typu action.