How is a thunk different from a regular action?
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:
const increment = {
type: 'INCREMENT',
payload: 1
}You pass it to the store:
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.
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:
- runs asynchronous code (an API request),
- and only then
dispatches 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:
dispatch({ type: 'LOGIN_SUCCESS', payload: user })Updates the store right away.
Thunk action:
dispatch(loginUser(credentials))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:
- we start loading (
LOGIN_START), - we wait for the server response,
- we finish with a success or error action.
5. What happens inside Redux
Without a thunk:
dispatch({ type: 'INCREMENT' })
↓
reducer(state, action)
↓
new stateWith a thunk:
dispatch(fetchUser(5))
↓
redux-thunk sees that this is a function
↓
calls it -> fetch API -> dispatch regular actions
↓
reducer processes them
↓
new state6. 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
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.
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.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.