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

如何用单个Redux-Toolkit异步Thunk与extra reducer处理多API请求

复用Redux-Toolkit异步Thunk与Extra Reducer的方案

核心思路

通过给异步Thunk传入实体类型标识和API调用函数,让单个Thunk能处理不同资源的请求;同时编写通用的extra reducer生成函数,根据实体类型过滤action,避免多个slice误响应同一action导致的异常。

实现步骤

1. 创建通用异步Thunk

这个Thunk接收entityType(区分是公司还是客户)和fetchFn(实际的API请求函数)作为参数,请求成功/失败时把实体类型和数据/错误信息一起返回:

import { createAsyncThunk } from '@reduxjs/toolkit';

export const fetchEntity = createAsyncThunk(
  'entities/fetch',
  async ({ entityType, fetchFn }, { rejectWithValue }) => {
    try {
      const response = await fetchFn();
      return { entityType, data: response.data };
    } catch (error) {
      return rejectWithValue({ entityType, error: error.response.data });
    }
  }
);

2. 编写通用Extra Reducer生成函数

生成对应实体类型的extra reducer逻辑,只处理与当前实体匹配的action:

export const createEntityExtraReducers = (entityType) => ({
  pending: (state) => {
    state.loading = true;
    state.error = null;
  },
  fulfilled: (state, action) => {
    if (action.payload.entityType === entityType) {
      state.loading = false;
      state.data = action.payload.data;
    }
  },
  rejected: (state, action) => {
    if (action.payload.entityType === entityType) {
      state.loading = false;
      state.error = action.payload.error;
    }
  },
});

3. 在Slice中复用通用逻辑

Companies Slice

import { createSlice } from '@reduxjs/toolkit';
import { fetchEntity, createEntityExtraReducers } from './genericEntities';

const initialState = {
  data: [],
  loading: false,
  error: null,
};

const companiesSlice = createSlice({
  name: 'companies',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    const reducers = createEntityExtraReducers('company');
    builder
      .addCase(fetchEntity.pending, reducers.pending)
      .addCase(fetchEntity.fulfilled, reducers.fulfilled)
      .addCase(fetchEntity.rejected, reducers.rejected);
  },
});

export default companiesSlice.reducer;

Clients Slice

import { createSlice } from '@reduxjs/toolkit';
import { fetchEntity, createEntityExtraReducers } from './genericEntities';

const initialState = {
  data: [],
  loading: false,
  error: null,
};

const clientSlice = createSlice({
  name: 'clients',
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    const reducers = createEntityExtraReducers('client');
    builder
      .addCase(fetchEntity.pending, reducers.pending)
      .addCase(fetchEntity.fulfilled, reducers.fulfilled)
      .addCase(fetchEntity.rejected, reducers.rejected);
  },
});

export default clientSlice.reducer;

4. 组件中调用Thunk

传入对应的实体类型和API请求函数即可:

// 获取公司列表
dispatch(fetchEntity({
  entityType: 'company',
  fetchFn: () => api.get('/companies')
}));

// 获取客户列表
dispatch(fetchEntity({
  entityType: 'client',
  fetchFn: () => api.get('/clients')
}));

扩展优化

  • 如果需要处理创建、更新、删除等更多异步操作,可以仿照fetchEntity创建通用的createEntity、updateEntity等Thunk,同时扩展createEntityExtraReducers支持更多action类型。
  • 可以把initialState也封装成通用函数,进一步减少slice间的重复代码。

内容的提问来源于stack exchange,提问作者Mohan Dhila

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 10:07:02