Що робить redux-thunk?
Коротка відповідь
redux-thunk- це middleware (прошарок) для Redux, який дозволяє відправляти не тільки об'єкти (actions), а й функції (thunks).Це потрібно, щоб виконувати асинхронні операції - запити до API, таймери, побічні ефекти тощо.
Проблема без redux-thunk
За замовчуванням Redux може обробляти лише синхронні actions - прості об'єкти:
store.dispatch({ type: 'LOGIN_SUCCESS', payload: user })Але якщо тобі потрібно:
- сходити на сервер,
- почекати відповідь,
- потім тільки оновити store - то звичайний Redux цього не вміє.
Redux очікує одразу готову дію, а не процес.
Що робить redux-thunk
redux-thunk перехоплює dispatch(action) і перевіряє:
якщо ти передав функцію, а не об'єкт - він виконає її.
Всередині цієї функції ти отримуєш доступ до dispatch і getState.
Тобто тепер можна писати асинхронні actions.
Приклад без Thunk
Не можна:
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
Можна:
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 })
}
}І потім:
store.dispatch(fetchUser(5))Що відбувається:
- Redux Thunk бачить, що action - це функція.
- Він викликає її, передаючи
dispatchіgetState. - Функція робить запит.
- Коли дані приходять - вона сама викликає звичайні actions (
USER_FETCH_SUCCESS).
Під капотом (реалізація redux-thunk у 5 рядках)
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():
const store = configureStore({
reducer: rootReducer,
})Ти можеш одразу використовувати асинхронні дії через:
createAsyncThunk()(рекомендований спосіб)- або писати свої
thunk-функції вручну.
Приклад з RTK createAsyncThunk
Redux Toolkit робить те саме, але простіше:
export const fetchUser = createAsyncThunk('user/fetch', async (id) => {
const res = await fetch(`/api/users/${id}`)
return await res.json()
})RTK автоматично створює 3 екшени:
user/fetch/pendinguser/fetch/fulfilleduser/fetch/rejected
і ти просто обробляєш їх у extraReducers.
Коли використовувати redux-thunk
Коли потрібно:
- Виконати асинхронний запит до API
- Почекати результат перед оновленням стану
- Отримати дані зі store перед дією
- Виконати послідовність викликів
dispatch()
Візуально
dispatch(fetchUser(5))
│
▼
[redux-thunk перевіряє]
│
├── якщо об'єкт → йде в reducer
└── якщо функція → викликає її з (dispatch, getState)
│
▼
async API-запит
│
▼
dispatch({ type: 'USER_FETCH_SUCCESS', payload: data })Підсумок
| Що робить | Опис |
|---|---|
redux-thunk | Middleware, що дозволяє dispatchити функції |
| Основна ціль | Асинхронні дії (API, таймери, побічні ефекти) |
| Що отримує thunk | dispatch, getState |
| Коли використовується | При завантаженні даних, логіні, затримках тощо |
| В RTK | Вже вбудований у configureStore() |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.