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

Redux Toolkit中如何通过Action Type调用createSlice内的Action?

问题:Redux Toolkit中能否通过Action Type直接dispatch Action?

我在slice中定义的Action带有Type,想通过dispatch({type:'filter/category', payload:'change state'})这样的方式调用该Action,但尝试后状态并未改变。请问在Redux Toolkit中是否可以实现这一需求,还是需要迁移至Redux?

补充信息

  • 已遵循Redux官方代码分割文档实现动态注入Reducer
  • 有可运行仓库用于复现问题

相关代码

通用Slice创建逻辑

export interface GenericState<T> {}
export const createGenericSlice = <T, Reducers extends SliceCaseReducers<GenericState<T>>>({
  name = 'filter',
  initialState,
  reducers,
}: {
  name: string;
  initialState: GenericState<T>;
  reducers: ValidateSliceCaseReducers<GenericState<T>, Reducers>;
}) => {
  return createSlice({
    name,
    initialState,
    reducers: {
      loadFilterOptions: (state, action: PayloadAction<any>) => {
        state = action.payload;
        return state;
      },
      ...reducers,
    },
  });
};

export const wrappedSlice = (reducers: any, initialState: any) =>
  createGenericSlice({
    name: 'filter',
    initialState: initialState as GenericState<[]>,
    reducers: {
      ...reducers,
    },
  });

Reducer合并逻辑

import { combineReducers } from 'redux';

const initialReducers = {};
export const createReducer = (asyncReducers = {}) => {
  return combineReducers({
    ...initialReducers,
    ...asyncReducers,
  });
};

export default createReducer;

Store配置

import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
import createReducer from './rootReducer';

export function initStore() {
  return configureStore({
    reducer: createReducer(),
    middleware: (getDefaultMiddleware) => [...getDefaultMiddleware()],
  });
}
const store = initStore();

export function injectAsyncReducer(key: any, asyncReducer: any) {
  asyncReducer[key] = asyncReducer;
  store.replaceReducer(createReducer(asyncReducer));
}

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
export type AppThunk<ReturnType = void> = ThunkAction<ReturnType, RootState, unknown, Action<string>>;

export default store;

动态注入Reducer的调用

injectAsyncReducer('test', this.reducerCollection.caseReducers.category);

当前核心疑问:如何通过Action Type正确dispatch Action,例如调用dispatch({type:"filter/load", payload:data})?


解决方案

Redux Toolkit完全支持通过Action Type直接dispatch Action,无需迁移至原生Redux。你的问题源于代码实现中的几个错误,修正后即可正常工作:

1. 修复动态注入Reducer的逻辑错误

当前injectAsyncReducer函数存在循环引用问题:asyncReducer[key] = asyncReducer会导致传入的reducer对象被修改为包含自身的循环结构,导致combineReducers无法正确处理。

修正后的代码:

// 维护已注入的reducers集合,避免重复注入
let injectedReducers: Record<string, any> = {};

export function injectAsyncReducer(key: string, asyncReducer: any) {
  if (!injectedReducers[key]) {
    injectedReducers[key] = asyncReducer;
    // 传入新的reducers集合给createReducer
    store.replaceReducer(createReducer(injectedReducers));
  }
}

2. 确保Action Type与slice定义完全匹配

createSlice会自动生成[sliceName]/[reducerName]格式的Action Type。例如你在slice中定义的reducer是loadFilterOptions,slice名称为filter,则对应的Action Type是filter/loadFilterOptions,而非filter/load——这是常见的错误点。

正确的dispatch写法应为:

dispatch({type:"filter/loadFilterOptions", payload:data})

3. 修正slice中的状态更新逻辑

虽然直接返回新状态在Immer中是允许的,但更规范的写法是直接修改状态(Immer会自动处理不可变更新),或者确保返回的是全新的状态对象:

loadFilterOptions: (state, action: PayloadAction<any>) => {
  // 直接返回新状态,确保覆盖原状态
  return { ...action.payload };
}

4. 确保注入的是完整slice reducer而非单个caseReducer

当前代码中注入的是this.reducerCollection.caseReducers.category(单个case reducer),但combineReducers需要的是完整的slice reducer。正确的注入方式应该是传入整个slice的reducer:

// 假设你创建了一个categorySlice
const categorySlice = wrappedSlice(/* 你的reducers */, /* 初始状态 */);
// 注入完整的slice reducer
injectAsyncReducer('test', categorySlice.reducer);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 07:25:20