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

能否将独立文件中的自定义actions传入createAsyncThunk?

关于createAsyncThunk分离action类型的可行性分析

结论:可以实现,但确实属于Redux生态中的反模式

实现步骤

  • 先在独立文件中定义action类型常量:
    // actionTypes.js
    export const FETCH_DATA_PENDING = 'FETCH_DATA_PENDING';
    export const FETCH_DATA_FULFILLED = 'FETCH_DATA_FULFILLED';
    export const FETCH_DATA_REJECTED = 'FETCH_DATA_REJECTED';
    
  • 创建thunk时,手动覆盖自动生成的action类型:
    // fetchDataThunk.js
    import { createAsyncThunk } from '@reduxjs/toolkit';
    import { FETCH_DATA_PENDING, FETCH_DATA_FULFILLED, FETCH_DATA_REJECTED } from './actionTypes';
    
    const fetchDataThunk = createAsyncThunk(
      'tempPrefix',
      async (payload) => {
        // 异步请求逻辑
        const res = await fetch('/api/data');
        return res.json();
      }
    );
    
    // 替换为自定义的action类型
    fetchDataThunk.pending.type = FETCH_DATA_PENDING;
    fetchDataThunk.fulfilled.type = FETCH_DATA_FULFILLED;
    fetchDataThunk.rejected.type = FETCH_DATA_REJECTED;
    
    export default fetchDataThunk;
    
  • 在reducer中仅导入独立的action类型文件,无需引入thunk:
    // dataReducer.js
    import { createSlice } from '@reduxjs/toolkit';
    import { FETCH_DATA_PENDING, FETCH_DATA_FULFILLED, FETCH_DATA_REJECTED } from './actionTypes';
    
    const initialState = {
      data: null,
      loading: false,
      error: null
    };
    
    const dataSlice = createSlice({
      name: 'data',
      initialState,
      extraReducers: (builder) => {
        builder
          .addCase(FETCH_DATA_PENDING, state => {
            state.loading = true;
            state.error = null;
          })
          .addCase(FETCH_DATA_FULFILLED, (state, action) => {
            state.loading = false;
            state.data = action.payload;
          })
          .addCase(FETCH_DATA_REJECTED, (state, action) => {
            state.loading = false;
            state.error = action.error.message;
          });
      }
    });
    
    export default dataSlice.reducer;
    

为什么是反模式?

  • Redux Toolkit的核心设计目标之一就是自动管理action类型,手动分离会破坏这种封装性,增加代码维护成本——修改thunk逻辑时需要同步更新action类型文件,容易出现不一致问题
  • 官方推荐直接使用fetchDataThunk.fulfilled这类自动生成的action类型配合createSlice,代码更简洁且不易出错

更合理的替代方案

如果只是不想在reducer中导入thunk文件,可以利用typePrefix统一命名,再通过addMatcher匹配action类型:

// fetchDataThunk.js
export const fetchDataThunk = createAsyncThunk(
  'data/fetchData',
  async (payload) => {
    const res = await fetch('/api/data');
    return res.json();
  }
);

// dataReducer.js
import { createSlice } from '@reduxjs/toolkit';

const initialState = { /* ... */ };

const dataSlice = createSlice({
  name: 'data',
  initialState,
  extraReducers: (builder) => {
    builder
      .addMatcher(
        action => action.type.startsWith('data/fetchData/pending'),
        state => { state.loading = true; }
      )
      .addMatcher(
        action => action.type.startsWith('data/fetchData/fulfilled'),
        (state, action) => { state.loading = false; state.data = action.payload; }
      )
      .addMatcher(
        action => action.type.startsWith('data/fetchData/rejected'),
        (state, action) => { state.loading = false; state.error = action.error.message; }
      );
  }
});

内容的提问来源于stack exchange,提问作者Konstanitnos Schoinas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 23:47:26