React Redux(Thunk)中整合加载Spinner的三个Reducer动作的正确方式
Hey there! Let's get your Redux async workflow sorted properly. The main thing to note here is that Redux reducers are pure functions—they can't handle asynchronous logic directly. To manage the full flow (start fetching → fetch data → finish fetching), we'll use Redux Thunk middleware, which lets us write action creators that return functions instead of plain objects. This way, we can dispatch multiple actions at different stages of the async process.
Step 1: Set Up Redux Thunk
First, make sure you have Redux Thunk installed and configured in your Redux store:
npm install redux-thunk # or yarn add redux-thunk
Then update your store configuration to apply the middleware:
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import reducer from './your-reducer-file'; const store = createStore( reducer, applyMiddleware(thunk) // Add Thunk middleware here );
Step 2: Refactor Your Async Data Fetching Function
Your original requestSideBarData function modifies the state directly, which breaks Redux's immutability rules. Let's rewrite it to return the new data object instead:
const fetchSideBarDataApi = async (requests) => { // Map over the keys in requests to create axios promises const promises = Object.keys(requests).map(key => axios.post(`${ApiEndPoints.getDropDownHeaders}${key}`, requests) ); const results = await Promise.all(promises); // Create a new data object with the fetched results return Object.keys(requests).reduce((acc, key, index) => { acc[key] = results[index].data; return acc; }, {}); };
Step 3: Create a Thunk Action Creator
This will handle the full async flow: dispatch the "begin" action, run the async fetch, dispatch the "success" action with the new data, then dispatch the "end" action. We'll also fix the typo in your original action name (fetchSidebBatData → fetchSidebarData):
export const fetchSidebarData = (dateData, selections) => { return async (dispatch) => { // Dispatch action to mark fetch start dispatch({ type: actionTypes.FETCH_SIDEBAR_DATA_BEGIN }); try { const requests = { ...dateData, ...selections }; // Fetch data from API const newData = await fetchSideBarDataApi(requests); // Dispatch action to update state with fetched data dispatch({ type: actionTypes.FETCH_SIDEBAR_DATA_SUCCESS, // Renamed from REQUEST for clarity payload: newData }); } catch (error) { // Optional: Add error handling if needed dispatch({ type: actionTypes.FETCH_SIDEBAR_DATA_ERROR, payload: error.message }); } finally { // Dispatch action to mark fetch end (runs whether success or error) dispatch({ type: actionTypes.FETCH_SIDEBAR_DATA_END }); } }; };
Step 4: Update Your Reducer
Keep your reducer pure and handle each action type correctly, maintaining immutability:
const initState = { data: {}, isFetching: false, error: null }; // Added error state for optional handling const fetchSideBarDataBegin = (state) => { return { ...state, isFetching: true, error: null }; // Reset error on new fetch }; const fetchSideBarDataSuccess = (state, action) => { return { ...state, data: { ...state.data, ...action.payload } }; // Merge new data }; const fetchSideBarDataEnd = (state) => { return { ...state, isFetching: false }; }; const fetchSideBarDataError = (state, action) => { return { ...state, error: action.payload }; }; const reducer = (state = initState, action) => { switch (action.type) { case actionTypes.FETCH_SIDEBAR_DATA_BEGIN: return fetchSideBarDataBegin(state); case actionTypes.FETCH_SIDEBAR_DATA_SUCCESS: return fetchSideBarDataSuccess(state, action); case actionTypes.FETCH_SIDEBAR_DATA_END: return fetchSideBarDataEnd(state); case actionTypes.FETCH_SIDEBAR_DATA_ERROR: return fetchSideBarDataError(state, action); default: return state; } };
Key Improvements Explained
- Immutability: We never modify the original state object—we always return new objects using the spread operator (
...). - Separation of Concerns: Async logic lives in the thunk action creator, not the reducer. Reducers only handle state updates based on plain actions.
- Complete Flow: The thunk dispatches actions at every stage (start, success/error, end), so your state accurately reflects the fetch status.
- Error Handling: Added optional error state so you can display errors to users if the fetch fails.
Now when you call dispatch(fetchSidebarData(dateData, selections)), it will automatically handle the entire async flow, updating isFetching and data in your store correctly.
内容的提问来源于stack exchange,提问作者Shivam Sahil

