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

如何基于Redux单变量实现多API请求的独立加载指示器

Solution: Dynamic Independent Loading Indicators for Multiple API Requests

Great question—tracking individual loading states for each API call is crucial as your app scales, and moving away from a single isLoading flag is the right move. Here's how to implement this with minimal changes to your existing Redux setup:


Step 1: Update the Redux State Structure

First, replace the single isLoading boolean with an object that maps unique request identifiers to their loading status. This lets us track each request independently:

// reducer.js
export const initialState = { 
  isAuth: false, 
  loadingRequests: {}, // Key: request identifier, Value: boolean (loading status)
  btnDisable: false,
  isError: null
};

export default function(state = initialState, action) {
  switch (action.type) {
    case API_REQUEST:
      return {
        ...state,
        loadingRequests: {
          ...state.loadingRequests,
          [action.payload.requestKey]: true // Mark this request as loading
        }
      };
    case API_SUCCESS:
      return {
        ...state,
        loadingRequests: {
          ...state.loadingRequests,
          [action.payload.requestKey]: false // Mark this request as complete
        },
        isError: null
      };
    case API_FAILURE:
      return {
        ...state,
        loadingRequests: {
          ...state.loadingRequests,
          [action.payload.requestKey]: false // Mark this request as failed
        },
        isError: action.payload.error
      };
    case GETLIST:
      return {
        ...state,
        list: action.payload
      };
    default:
      return state;
  }
}

Step 2: Modify Action Creators to Include Request Keys

Update your action creators to pass a unique requestKey with each API action. This key will link the loading state to the specific request:

// action.js
export const API_REQUEST = 'API_REQUEST';
export const API_SUCCESS = 'API_SUCCESS';
export const API_FAILURE = 'API_FAILURE';
export const GETLIST = 'GETLIST';

// Reusable helper actions for API lifecycle
const apiRequest = (requestKey) => ({
  type: API_REQUEST,
  payload: { requestKey }
});

const apiSuccess = (requestKey) => ({
  type: API_SUCCESS,
  payload: { requestKey }
});

const apiFailure = (requestKey, error) => ({
  type: API_FAILURE,
  payload: { requestKey, error }
});

// Example action for your existing list request
export const getListRequest = () => {
  return (dispatch) => {
    const requestKey = 'dashboard_getList'; // Unique key for this request
    dispatch(apiRequest(requestKey));
    
    API.anygetcall()
      .then((res) => {
        dispatch(apiSuccess(requestKey));
        dispatch({ type: GETLIST, payload: res });
      })
      .catch((err) => {
        dispatch(apiFailure(requestKey, err));
      });
  };
};

// Example of another request (for a different widget)
export const getUserProfileRequest = () => {
  return (dispatch) => {
    const requestKey = 'dashboard_userProfile';
    dispatch(apiRequest(requestKey));
    
    API.getUserProfile()
      .then((res) => {
        dispatch(apiSuccess(requestKey));
        dispatch({ type: GET_USER_PROFILE, payload: res });
      })
      .catch((err) => {
        dispatch(apiFailure(requestKey, err));
      });
  };
};

Step 3: Use the Loading State in Components

In each widget/component, check the loading status for its specific request key to show the loading indicator:

// DashboardWidget.js (example component)
import { connect } from 'react-redux';
import { getListRequest } from './actions';

const DashboardListWidget = ({ isLoading, list, getListRequest }) => {
  // Fetch data on mount
  useEffect(() => {
    getListRequest();
  }, [getListRequest]);

  if (isLoading) {
    return <div className="widget-loader">Loading list...</div>;
  }

  return (
    <div className="dashboard-widget">
      {list.map(item => <div key={item.id}>{item.name}</div>)}
    </div>
  );
};

const mapStateToProps = (state) => ({
  // Check the specific request key for this widget
  isLoading: state.loadingRequests['dashboard_getList'] || false,
  list: state.list || []
});

export default connect(mapStateToProps, { getListRequest })(DashboardListWidget);

Key Workflow Adjustments

  1. Unique Request Keys: Assign a meaningful, unique key to every API call (e.g., dashboard_userProfile, settings_updatePreferences). This ensures no overlap in loading state tracking.
  2. Reusable API Helpers: The apiRequest, apiSuccess, and apiFailure helpers eliminate duplicate code across action creators.
  3. Component-Specific Loading Checks: Each component only cares about its own request key, so loading states don't bleed between widgets.
  4. Scalability: As you add more API calls, you just add new request keys—no need to modify the reducer or add new isLoading flags.

内容的提问来源于stack exchange,提问作者tapan dave

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:36:09