Reducers are inherently pure functions, which means they cannot directly manage async operations. Nevertheless, they can respond to dispatched actions, including those initiated before, during, or after an async process.
Common Pattern for Async Actions:
An async operation typically dispatches three types of actions:
REQUEST – before the async call starts (e.g., show loading spinner)
SUCCESS – when the async call succeeds (e.g., store data)
FAILURE – when the async call fails (e.g., show error)
Example with Thunk:
// action types
const FETCH_DATA_REQUEST = 'FETCH_DATA_REQUEST';
const FETCH_DATA_SUCCESS = 'FETCH_DATA_SUCCESS';
const FETCH_DATA_FAILURE = 'FETCH_DATA_FAILURE';
// reducer
const initialState = {
loading: false,
data: [],
error: null,
};
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.error,
};
default:
return state;
}
};