Skip to main content

Чим thunk відрізняється від звичайного action?

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

Звичайний action - це об'єкт, який описує що сталося (наприклад: { type: 'INCREMENT', payload: 1 }).

Thunk - це функція, яка описує що потрібно зробити (наприклад: dispatch -> API -> dispatch SUCCESS/ERROR).


1. Звичайний action

Redux за своєю природою синхронний. Кожна дія - це plain object (простий об'єкт) з обов'язковим полем type:

javascript
const increment = { type: 'INCREMENT', payload: 1 }

Ти передаєш його в store:

javascript
store.dispatch(increment)

-> Redux одразу викликає reducer -> reducer синхронно повертає новий стан.

Все просто і миттєво.


2. Thunk (асинхронний action)

Thunk - це функція, а не об'єкт. Коли Redux бачить функцію, він сам по собі не знає, що з нею робити - тому в справу вступає middleware redux-thunk.

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

Тут thunk - це "дія-процес", яка всередині себе:

  1. виконує асинхронний код (API-запит),
  2. і вже потім робить dispatch звичайних (синхронних) actions.

3. Порівняння в коді

ТипЩо цеЯк виглядаєЩо робить
Звичайний actionОб'єкт{ type: 'ADD_TODO', payload: 'Buy milk' }Одразу йде в reducer
ThunkФункція(dispatch, getState) => { ... }Виконує логіку (зазвичай асинхронну), потім dispatch'ить звичайні actions

4. Приклад у дії

Звичайний action:

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

Одразу оновить store.


Thunk action:

javascript
dispatch(loginUser(credentials))
javascript
const loginUser = (credentials) => async (dispatch) => { dispatch({ type: 'LOGIN_START' }) try { const res = await fetch('/api/login', { method: 'POST', body: JSON.stringify(credentials) }) const user = await res.json() dispatch({ type: 'LOGIN_SUCCESS', payload: user }) } catch (err) { dispatch({ type: 'LOGIN_ERROR', payload: err.message }) } }

Тут:

  1. починаємо завантаження (LOGIN_START),
  2. чекаємо відповіді від сервера,
  3. завершуємо дією успіху або помилки.

5. Що відбувається всередині Redux

Без thunk:

javascript
dispatch({ type: 'INCREMENT' }) reducer(state, action) новий стан

З thunk:

javascript
dispatch(fetchUser(5)) redux-thunk бачить, що це функція викликає її -> fetch API -> dispatch звичайних actions reducer обробляє їх новий стан

6. Головна різниця

КритерійЗвичайний ActionThunk
ТипОб'єктФункція
АсинхронністьНіТак
Куди йдеОдразу в reducerВ middleware (redux-thunk)
Може викликати інші actionsНіТак
Має доступ до dispatch / getStateНіТак
Використовується дляПростих змінСкладної логіки (запити, ланцюжки, таймери)

7. Візуально

javascript
Звичайний action: [dispatch][reducer][новий state] Thunk: [dispatch][redux-thunk middleware] виконує функцію → [dispatch звичайних actions][reducer]

8. Приклад у Redux Toolkit

Redux Toolkit включає redux-thunk за замовчуванням, а його аналог - це createAsyncThunk(), який автоматизує роботу з thunks.

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

Під капотом createAsyncThunk - це просто автоматично створений thunk з екшенами pending, fulfilled, rejected.


Підсумок

ВідмінністьЗвичайний ActionThunk
ТипОб'єкт { type, payload }Функція (dispatch, getState) => {}
ОбробляєтьсяОдразу в reducerMiddleware redux-thunk
АсинхронністьНемаєЄ
МетаОписати "що сталося"Описати "що потрібно зробити"
Може dispatch'ити інші actionsНіТак
Використовується дляПростих подійЗапитів, складної логіки

Коротко:

Звичайний action - це повідомлення про подію. Thunk - це функція-план дій, яка може виконувати асинхронну роботу і сама відправляти потрібні звичайні actions у потрібний момент.

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

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

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