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

sjb*_*sse 11 reactjs redux redux-toolkit

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

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

Run Code Online (Sandbox Code Playgroud)

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

Lin*_*ste 14

您可以使用“构建器回调”符号extraReducers完成此操作。使用此表示法,您可以通过向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
    );
Run Code Online (Sandbox Code Playgroud)

我们可以将其与您现有的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;
      }
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

或者使用 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;
      }
    );
  }
});
Run Code Online (Sandbox Code Playgroud)

  • 有趣的是,这曾经是非常干净的代码,具有可读性,但现在却不是。我认为 Redux 工具包应该让 redux 的使用变得更加简单。 (3认同)
  • `isAnyOf` 现在实际上是 redux-toolkit https://redux-toolkit.js.org/api/matching-utilities#isanyof 的一部分但是,它不支持您在此处介绍的字符串:) (2认同)