You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Redux(Thunk)中整合加载Spinner的三个Reducer动作的正确方式

How to Integrate Redux Async Flow for Sidebar Data Fetching

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 19:12:56