How to Handle Async in Redux: Fix and Best Practices
redux-thunk or redux-saga that lets you write async logic inside action creators. This avoids dispatching plain objects only and allows dispatching functions that perform async calls and then dispatch actions with results.Why This Happens
Redux by default expects actions to be plain objects. When you try to dispatch a function or a promise directly for async work, Redux throws an error or ignores it because it can't handle async code on its own.
import { createStore } from 'redux'; const reducer = (state = { data: null }, action) => { switch (action.type) { case 'SET_DATA': return { ...state, data: action.payload }; default: return state; } }; const store = createStore(reducer); // Async action creator returning a function (not supported by default) const fetchData = () => { return (dispatch) => { fetch('https://api.example.com/data') .then(response => response.json()) .then(data => dispatch({ type: 'SET_DATA', payload: data })); }; }; store.dispatch(fetchData());
The Fix
Use middleware like redux-thunk that allows dispatching functions. This middleware intercepts function actions, runs the async code inside, and dispatches plain object actions when ready.
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; const reducer = (state = { data: null }, action) => { switch (action.type) { case 'SET_DATA': return { ...state, data: action.payload }; default: return state; } }; const store = createStore(reducer, applyMiddleware(thunk)); const fetchData = () => { return async (dispatch) => { const response = await fetch('https://api.example.com/data'); const data = await response.json(); dispatch({ type: 'SET_DATA', payload: data }); }; }; store.dispatch(fetchData());
Prevention
Always use middleware like redux-thunk or redux-saga for async logic in Redux. Keep action creators pure by dispatching plain objects only after async calls. Use linting rules to warn if non-plain objects are dispatched. Structure async code clearly to avoid side effects in reducers.
Related Errors
Common related errors include dispatching promises directly, which Redux also rejects, or trying to perform async calls inside reducers, which must be pure and synchronous. The fix is to keep async logic in middleware or action creators and reducers pure.