Redux Thunk Middleware

3.1.0 · active · verified Wed Apr 22

Redux Thunk is a middleware for Redux that enables writing action creators that return functions (thunks) instead of plain action objects. These thunk functions receive the `dispatch` and `getState` methods of the Redux store, allowing for asynchronous logic, conditional dispatching, and interaction with the store's current state. The current stable version is 3.1.0, released in conjunction with major updates to the entire Redux ecosystem, including Redux Toolkit 2.0, Redux core 5.0, and React-Redux 9.0. Its release cadence is closely tied to the broader Redux project releases. A key differentiator is its simplicity and official endorsement as the standard approach for handling async logic in Redux, often being included by default in `configureStore` from Redux Toolkit. It also supports injecting custom arguments, facilitating dependency injection patterns for services or APIs.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates the manual setup of Redux Thunk with `createStore` and `applyMiddleware` in TypeScript, including a basic asynchronous thunk action.

import { createStore, applyMiddleware, AnyAction } from 'redux';
import { thunk, ThunkAction, ThunkDispatch } from 'redux-thunk';

interface RootState {
  count: number;
}

const initialState: RootState = { count: 0 };

function rootReducer(state: RootState = initialState, action: AnyAction): RootState {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    case 'DECREMENT':
      return { ...state, count: state.count - 1 };
    default:
      return state;
  }
}

// Apply the thunk middleware
const store = createStore(rootReducer, applyMiddleware(thunk));

// Define a simple asynchronous thunk action
const incrementAsync = (amount: number): ThunkAction<void, RootState, unknown, AnyAction> =>
  (dispatch: ThunkDispatch<RootState, unknown, AnyAction>, getState) => {
    console.log(`Current count before async: ${getState().count}`);
    setTimeout(() => {
      dispatch({ type: 'INCREMENT', payload: amount });
      console.log(`Current count after async: ${getState().count}`);
    }, 1000);
  };

console.log('Initial state:', store.getState());

(store.dispatch as ThunkDispatch<RootState, unknown, AnyAction>)(incrementAsync(1));

console.log('State after dispatching async thunk (will update later):', store.getState());

view raw JSON →