Введение в thunks в Redux
В предыдущей главе мы организовали работу
сервера, базы данных и клиента для
обмена данными. Теперь нам необходимо
навести последний мостик, который поможет
нашему 'синхронно'
организованному Redux
приложению взаимодействовать с асинхронным
клиентом, которого мы создали на последнем
уроке предыдущей главы, чтобы отправлять
запросы и получать необходимые данные в ответе.
Как мы помним из первых уроков предыдущего
раздела, Redux ничего не знает о работе с
асинхронной логикой и для этого мы будем
использовать thunk middleware. Этот middleware
позволяет работать с отправленными actions,
использовать в коде нашего thunk dispatch
и
getState
методы store, а также помогать
методу dispatch
работать не только с
обычными JS объектами, но и с такими сущностями,
как функции и промисы.
Обычно thunk-функция вызывается с двумя
аргументами dispatch
и getState
(при необходимости), которыми можно пользоваться
в теле этой функции. С помощью нее можно
отправлять обычные экшены. Также
ее можно отправлять через store.dispatch
.
Пример такой функции приведен ниже:
const changeColorThunk = (dispatch, getState) => {
const colorBefore = getState()
console.log(`Old Color: ${colorBefore.color}`)
dispatch(changeColor())
const colorAfter = getState()
console.log(`New Color: ${colorAfter.color}`)
}
store.dispatch(changeColorThunk)
Давайте теперь откроем наше приложение с
продуктами. Первое, что мы должны получить
от сервера при запуске приложения - это
список продуктов. Так как обычно thunks
пишутся в слайс-файлах, то мы откроем файл
productsSlice.js
.
Радостная новость заключается в том, что
нам не надо возиться с установкой Redux Thunk,
так как функция configureStore
из RTK
уже сделает это за нас. Поэтому просто добавим
createAsyncThunk
в импорт в файле:
import { createSlice, nanoid, createAsyncThunk } from '@reduxjs/toolkit'
Добавим также в импорт и наш клиент:
import { client } from '../../api/client'
А теперь при помощи createAsyncThunk
создадим наш первый thunk для получения
продуктов, сделаем это сразу после
объявления объекта initialState
:
export const fetchProducts = createAsyncThunk()
Первым параметром createAsyncThunk
будет
принимать строку для типа генерируемого
action, а вторым - колбэк-функцию для
payload
, которая в результате вернет
либо данные, либо промис с ошибкой (смотрите
файл 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.