Skip to main content

Що робить redux-thunk?

Коротка відповідь

redux-thunk - це middleware (прошарок) для Redux, який дозволяє відправляти не тільки об'єкти (actions), а й функції (thunks).

Це потрібно, щоб виконувати асинхронні операції - запити до API, таймери, побічні ефекти тощо.


Проблема без redux-thunk

За замовчуванням Redux може обробляти лише синхронні actions - прості об'єкти:

javascript
store.dispatch({ type: 'LOGIN_SUCCESS', payload: user })

Але якщо тобі потрібно:

  • сходити на сервер,
  • почекати відповідь,
  • потім тільки оновити store - то звичайний Redux цього не вміє.

Redux очікує одразу готову дію, а не процес.


Що робить redux-thunk

redux-thunk перехоплює dispatch(action) і перевіряє: якщо ти передав функцію, а не об'єкт - він виконає її. Всередині цієї функції ти отримуєш доступ до dispatch і getState.

Тобто тепер можна писати асинхронні actions.


Приклад без Thunk

Не можна:

javascript
store.dispatch(async () => { const res = await fetch('/api/user') const data = await res.json() store.dispatch({ type: 'SET_USER', payload: data }) })

Redux скаже:

"Action має бути об'єктом, а ти мені дав функцію!"


Приклад з redux-thunk

Можна:

javascript
const fetchUser = (id) => { return async (dispatch, getState) => { dispatch({ type: 'USER_FETCH_START' }) const res = await fetch(`/api/users/${id}`) const data = await res.json() dispatch({ type: 'USER_FETCH_SUCCESS', payload: data }) } }

І потім:

javascript
store.dispatch(fetchUser(5))

Що відбувається:

  1. Redux Thunk бачить, що action - це функція.
  2. Він викликає її, передаючи dispatch і getState.
  3. Функція робить запит.
  4. Коли дані приходять - вона сама викликає звичайні actions (USER_FETCH_SUCCESS).

Під капотом (реалізація redux-thunk у 5 рядках)

javascript
const thunkMiddleware = store => next => action => { if (typeof action === 'function') { return action(store.dispatch, store.getState) } return next(action) }

Механізм:

  • Якщо action - це функція -> викликаємо її.
  • Якщо це об'єкт -> передаємо далі у стандартний Redux-потік.

У зв'язці з Redux Toolkit

Redux Toolkit вже включає redux-thunk за замовчуванням у configureStore():

javascript
const store = configureStore({ reducer: rootReducer, })

Ти можеш одразу використовувати асинхронні дії через:

  • createAsyncThunk() (рекомендований спосіб)
  • або писати свої thunk-функції вручну.

Приклад з RTK createAsyncThunk

Redux Toolkit робить те саме, але простіше:

javascript
export const fetchUser = createAsyncThunk('user/fetch', async (id) => { const res = await fetch(`/api/users/${id}`) return await res.json() })

RTK автоматично створює 3 екшени:

  • user/fetch/pending
  • user/fetch/fulfilled
  • user/fetch/rejected

і ти просто обробляєш їх у extraReducers.


Коли використовувати redux-thunk

Коли потрібно:

  • Виконати асинхронний запит до API
  • Почекати результат перед оновленням стану
  • Отримати дані зі store перед дією
  • Виконати послідовність викликів dispatch()

Візуально

javascript
dispatch(fetchUser(5)) [redux-thunk перевіряє] ├── якщо об'єкт → йде в reducer └── якщо функція → викликає її з (dispatch, getState) async API-запит dispatch({ type: 'USER_FETCH_SUCCESS', payload: data })

Підсумок

Що робитьОпис
redux-thunkMiddleware, що дозволяє dispatchити функції
Основна цільАсинхронні дії (API, таймери, побічні ефекти)
Що отримує thunkdispatch, getState
Коли використовуєтьсяПри завантаженні даних, логіні, затримках тощо
В RTKВже вбудований у configureStore()

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.