Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що робить redux-thunk?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`redux-thunk`** - це **middleware** (прошарок) для Redux, який дозволяє **відправляти не тільки об'єкти (actions)**, а й **функції (thunks)**. **Ключове:** це потрібно, щоб виконувати асинхронні операції - запити до API, таймери, побічні ефекти тощо.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Коротка відповідь > `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-thunk` | Middleware, що дозволяє `dispatch`ити функції | | **Основна ціль** | Асинхронні дії (API, таймери, побічні ефекти) | | **Що отримує thunk** | `dispatch`, `getState` | | **Коли використовується** | При завантаженні даних, логіні, затримках тощо | | **В RTK** | Вже вбудований у `configureStore()` |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.