Blog>
Snippets

Handling Asynchronous Actions with Redux Thunk

Write a Redux Thunk middleware that dispatches actions to fetch data from an API and updates the Redux store upon success or failure.
// actions.js
// Define action types
const FETCH_DATA_REQUEST = 'FETCH_DATA_REQUEST';
const FETCH_DATA_SUCCESS = 'FETCH_DATA_SUCCESS';
const FETCH_DATA_FAILURE = 'FETCH_DATA_FAILURE';

// Action creators
const fetchDataRequest = () => ({
  type: FETCH_DATA_REQUEST
});

const fetchDataSuccess = (data) => ({
  type: FETCH_DATA_SUCCESS,
  payload: data
});

const fetchDataFailure = (error) => ({
  type: FETCH_DATA_FAILURE,
  payload: error
});

// Thunk action creator
const fetchMyApiData = () => {
  return (dispatch) => {
    dispatch(fetchDataRequest());
    fetch('/my-api-endpoint')
      .then(response => response.json())
      .then(data => dispatch(fetchDataSuccess(data)))
      .catch(error => dispatch(fetchDataFailure(error.message)));
  };
};

export { fetchMyApiData, FETCH_DATA_REQUEST, FETCH_DATA_SUCCESS, FETCH_DATA_FAILURE };
Defines the actions and the thunk action creator for fetching data from an API. The thunk dispatches a request action before making the API call, then dispatches either a success or failure action based on the API response.
// reducers.js
import { FETCH_DATA_REQUEST, FETCH_DATA_SUCCESS, FETCH_DATA_FAILURE } from './actions';

const initialState = {
  loading: false,
  data: [],
  error: null
};

// Reducer handling the actions
const dataReducer = (state = initialState, action) => {
  switch (action.type) {
    case FETCH_DATA_REQUEST:
      return { ...state, loading: true, error: null };
    case FETCH_DATA_SUCCESS:
      return { ...state, loading: false, data: action.payload };
    case FETCH_DATA_FAILURE:
      return { ...state, loading: false, error: action.payload };
    default:
      return state;
  }
};

export default dataReducer;
Defines the reducer to handle data fetching actions. Updates the state based on the action type—request, success, or failure.
// store.js
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

// Create store with Thunk middleware
const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);

export default store;
Creates the Redux store and applies the Redux Thunk middleware to allow for async action dispatches.