对 redux 工具包的 createSlice 中的多个操作做出反应

Posted

技术标签:

【中文标题】对 redux 工具包的 createSlice 中的多个操作做出反应【英文标题】:react to multiple actions in redux toolkit's createSlice 【发布时间】:2021-01-12 20:11:47 【问题描述】:

我正在重构我的 reducer 以使用 redux-toolkit 的 createSlice。 现在我有一个非常基于事件的 reducer,有时需要针对不同的操作进行类似的状态更新 . 使用原始的 switch/case 声明,这不是问题:

        case ActionTypes.CREATION_CANCELLED:
        case ActionTypes.NEW_MARKER_INFOWINDOW_CLOSED:
        case ActionTypes.MARKER_SELECTED:
            return ...state, isCreating: false;

createSlice 函数可以实现这种行为吗?

【问题讨论】:

我不确定它是否支持开箱即用,但您始终可以创建一个辅助函数,该函数采用 state 并返回相同的状态但使用 isCreating: false 并在多个地方。 【参考方案1】:

您可以使用the extraReducers "builder callback" notation 执行此操作。使用这种表示法,您可以通过将案例添加到 builder 对象来创建减速器。 builder.addMatcher 函数的第一个参数决定了哪些动作类型匹配这种情况。

如果您的操作共享一个通用的字符串格式,您可以使用基于字符串的匹配器(例如 action.type.endsWith('/rejected'))以相同的方式处理所有 rejected 操作。

否则,您可以定义自己的自定义匹配器函数,该函数接受 action 并返回 boolean 是否匹配。

由于我们想要匹配多种动作类型,我们可以为此创建一个助手。

// helper function to match any actions in a provided list
// actions can be `string` types or redux-toolkit action creators
const isAnyOf = (...matchers: Array<string |  type: string >) => 
  ( action: AnyAction ) =>
    matchers.some((matcher) =>
      typeof matcher === "string"
        ? matcher === action.type
        : matcher.type === action.type
    );

我们可以将它与您现有的 string 常量一起使用:

const slice = createSlice(
  name: "some name",
  initialState: 
    someProp: [],
    isCreating: false
  ,
  reducers: ,
  extraReducers: (builder) => 
    return builder.addMatcher(
      isAnyOf(
        ActionTypes.CREATION_CANCELLED,
        ActionTypes.NEW_MARKER_INFOWINDOW_CLOSED,
        ActionTypes.MARKER_SELECTED
      ),
      (state, action) => 
        state.isCreating = false;
      
    );
  
);

或者使用 Redux Toolkit 动作创建者:

const creationCancelled = createAction("CREATION_CANCELLED");
const newMarkerInfoWindowClosed = createAction("NEW_MARKER_INFOWINDOW_CLOSED");
const markerSelected = createAction("MARKER_SELECTED");

const slice = createSlice(
  name: "some name",
  initialState: 
    someProp: [],
    isCreating: false
  ,
  reducers: ,
  extraReducers: (builder) => 
    return builder.addMatcher(
      isAnyOf(creationCancelled, newMarkerInfoWindowClosed, markerSelected),
      (state, action) => 
        state.isCreating = false;
      
    );
  
);

【讨论】:

isAnyOf 现在实际上是 redux-toolkit redux-toolkit.js.org/api/matching-utilities#isanyof 的一部分,但是,它不支持您在此处介绍的字符串 :)

以上是关于对 redux 工具包的 createSlice 中的多个操作做出反应的主要内容,如果未能解决你的问题,请参考以下文章

Redux - createSlice 内的标准化嵌套数据组织

如何使用 Redux Tool Kit 的“createSlice”设置一个单元测试 Redux?

Redux 工具包操作不知何故不同步

如何将 redux-toolkit createSlice 与 React 类组件一起使用

如何使用 redux-toolkit 中的 createSlice 方法在不同的 reducer 函数中使用单个动作类型

如何重用 Redux Toolkit createSlice 函数中的 reducer 逻辑?