Въведение в thunks в Redux

В предишната глава ние организирахме работата на сървъра, базата данни и клиента за обмен на данни. Сега ние трябва да направим последния мост, който ще помогне на нашето 'синхронно' организирано Redux приложение да взаимодейства с асинхронния клиент, който ние създадохме в последния урок на предишната глава, за да изпращаме заявки и да получаваме необходимите данни в отговор.

Както си спомняме от първите уроци на предишния раздел, Redux не знае нищо за работа с асинхронна логика и за това ние ще използваме thunk middleware. Този middleware позволява работа с изпратени actions, използване в кода на нашия thunk dispatch и getState методи на store, както и помага на метода dispatch да работи не само с обикновени JS обекти, но и с такива entities, като функции и promises.

Обикновено thunk-функция се извиква с два аргумента dispatch и getState (при необходимост), които могат да се използват в тялото на тази функция. С помощта на нея може да се изпращат обикновени actions. Също така тя може да се изпраща чрез store.dispatch. Пример за такава функция е даден по-долу:

jsxconst 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 се пишат в slice-файлове, ние ще отворим файла productsSlice.js.

Радостната новина е, че ние не трябва да се занимаваме с инсталиране на Redux Thunk, тъй като функцията configureStore от RTK вече ще направи това вместо нас. Затова просто ще добавим createAsyncThunk в импорта във файла:

products/productsSlice.jsimport { createSlice, nanoid, createAsyncThunk } from '@reduxjs/toolkit'

Добавете също в импорта и нашия клиент:

products/productsSlice.jsimport { client } from '../../api/client'

А сега чрез createAsyncThunk създайте нашия първи thunk за получаване на продукти, направете това веднага след декларирането на обекта initialState:

products/productsSlice.jsexport const fetchProducts = createAsyncThunk()

Първият параметър на createAsyncThunk ще приема стринг за типа генериран action, а вторият - callback-функция за payload, която в резултат ще върне или данни, или promise с грешка (вижте файла client.js). В кода на функцията ние извикваме client.get и му подаваме пътя, който ние посочихме на сървъра (погледнете приеманите параметри http.get в server.js):

products/productsSlice.jsexport const fetchProducts = createAsyncThunk(
  'products/fetchProducts',
  async () => {
    const response = await client.get('/fakeServer/products')
    return response.data
  }
)
Задание 1

Отворете вашето приложение със студенти. Отворете в него файла studentsSlice.js. Импортирайте в него функцията createAsyncThunk за създаване на thunk, както и client за изпращане на API заявки към сървъра.

Задание 2

Веднага след декларирането на обекта initialState с помощта на createAsyncThunk създайте thunk fetchStudents за получаване на списък със студенти, който ще изпраща GET-заявка на адрес /fakeServer/students, посочен във вашия файл server.js, и ще връща response.data, както е показано в материалите на урока. Като първи параметър за createAsyncThunk посочете стринг students/fetchStudents за типа на action.