Suggest an editImprove this articleRefine the answer for “How is a thunk different from a regular action?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)A **regular action** is an **object** describing *what happened* (for example: `{ type: 'INCREMENT', payload: 1 }`). A **thunk** is a **function** describing *what needs to be done* (for example: `dispatch -> API -> dispatch SUCCESS/ERROR`). **Key point:** a thunk has access to `dispatch`/`getState` and can dispatch other actions, while a regular action goes straight to the reducer.Shown above the full answer for quick recall.Answer (EN)Image## Short answer > A **regular action** is an **object** that describes *what happened* > (for example: `{ type: 'INCREMENT', payload: 1 }`). > > A **thunk** is a **function** that describes *what needs to be done* > (for example: `dispatch -> API -> dispatch SUCCESS/ERROR`). --- ## 1. Regular action Redux is **synchronous** by nature. Every action is a **plain object** with a required `type` field: ```javascript const increment = { type: 'INCREMENT', payload: 1 } ``` You pass it to the store: ```javascript store.dispatch(increment) ``` -> Redux immediately calls the reducer -> the reducer synchronously returns a new state. Everything is simple and instant. --- ## 2. Thunk (an asynchronous action) A thunk is a **function, not an object**. When Redux sees a function, it doesn't know by itself what to do with it - so **redux-thunk middleware** comes into play. ```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 }) } } ``` Here **the thunk is an "action process"** that internally: 1. runs asynchronous code (an API request), 2. and only then `dispatch`es regular (synchronous) actions. --- ## 3. Comparison in code | Type | What it is | What it looks like | What it does | |---|---|---|---| | **Regular action** | Object | `{ type: 'ADD_TODO', payload: 'Buy milk' }` | Goes straight to the reducer | | **Thunk** | Function | `(dispatch, getState) => { ... }` | Runs logic (usually asynchronous), then dispatches regular actions | --- ## 4. Example in action ### Regular action: ```javascript dispatch({ type: 'LOGIN_SUCCESS', payload: user }) ``` Updates the store right away. --- ### 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 }) } } ``` Here: 1. we **start** loading (`LOGIN_START`), 2. we **wait** for the server response, 3. we **finish** with a success or error action. --- ## 5. What happens inside Redux Without a thunk: ```javascript dispatch({ type: 'INCREMENT' }) ↓ reducer(state, action) ↓ new state ``` With a thunk: ```javascript dispatch(fetchUser(5)) ↓ redux-thunk sees that this is a function ↓ calls it -> fetch API -> dispatch regular actions ↓ reducer processes them ↓ new state ``` --- ## 6. The main difference | Criterion | Regular Action | Thunk | |---|---|---| | Type | Object | Function | | Asynchronous | No | Yes | | Where it goes | Straight to the reducer | To middleware (`redux-thunk`) | | Can dispatch other actions | No | Yes | | Has access to `dispatch` / `getState` | No | Yes | | Used for | Simple changes | Complex logic (requests, chains, timers) | --- ## 7. Visually ```javascript Regular action: [dispatch] → [reducer] → [new state] Thunk: [dispatch] → [redux-thunk middleware] → runs the function → [dispatch regular actions] → [reducer] ``` --- ## 8. Example in Redux Toolkit Redux Toolkit includes `redux-thunk` by default, and its counterpart is `createAsyncThunk()`, which automates working with thunks. ```javascript export const fetchUser = createAsyncThunk('user/fetch', async (id) => { const res = await fetch(`/api/users/${id}`) return await res.json() }) ``` Under the hood, `createAsyncThunk` is simply an **automatically created thunk** with `pending`, `fulfilled`, `rejected` actions. --- ## Summary | Difference | Regular Action | Thunk | |---|---|---| | Type | Object `{ type, payload }` | Function `(dispatch, getState) => {}` | | Handled by | Straight to the reducer | `redux-thunk` middleware | | Asynchronous | No | Yes | | Purpose | Describe "what happened" | Describe "what needs to be done" | | Can dispatch other actions | No | Yes | | Used for | Simple events | Requests, complex logic | --- **In short:** > A regular action is a *message about an event*. > A thunk is a *function-plan of actions* that can do asynchronous work > and dispatch the necessary regular actions itself at the right moment.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.