如何在createSlice 的reducer 中获取状态值?

IT技术 javascript reactjs typescript redux redux-toolkit
2021-04-24 09:49:21

我在我的react项目中使用 redux-toolkit。在createSlice 的reducer 中,我想使用状态中现有的实体数组并附加新数组,然后再减少最终状态。但我无法获得状态值。

这是减速器代码

export const usersSlice = createSlice({
  name: "users",
  initialState: initialUsersState,
  reducers: {
    usersCreated: (state: UsersState, action) => {
      // in real, return count from the server and append the entities on front-end only?
      const { count, entities } = action.payload;
      const existingEntities = state.entities;
      const newEntities = [...existingEntities, ...entities];
      const totalCount = state.totalCount+count;
      return {
        ...state,
        entities: newEntities,
        totalCount: totalCount,
        listLoading: false,
        error: null,
      };
    },
}});

当我调试 state.entites 变量时,它看起来像这样

在此处输入图片说明

有没有办法访问 reducer/extraReducer 中的当前状态值以根据需要重新创建状态?

因为我认为直接在 reducer 之外使用状态值是一种不好的做法。如果我错了,请指导我。

编辑

@Linda Paiste 创建代码沙箱运行良好,这意味着我们可以访问 reducer 中的状态变量,但我们无法调试状态变量以深入挖掘该状态变量目前持有的内容,因为 Redux-toolkit 是以自己的方式处理状态......从调试屏幕截图中可以明显看出

在此处输入图片说明

3个回答

总结我和@karlmaxlopez 评论中的信息:

我将您的代码复制到CodeSandbox 演示中,发现代码确实按预期执行。state.entities即使在检查或记录的值state.entities显示为 a Proxy您也可以将其附加到数组,就像它是一个普通数组一样null

这是因为 redux-toolkit 使用 Immer 来防止您直接改变状态。在普通的 redux reducer 中,您会收到前一个state作为函数参数。作为用户,您有责任不对其进行变异,而是通过使用非变异方法(例如对象传播、数组连接等)返回具有更新值的新对象。这就是您在usersCreated减速器中所做的,这完全没问题。

但是 redux-toolkit 和 Immer 为如何编写 reducer 开辟了另一种可能性。Immer reducer 中state您的函数接收到的参数是“草稿”对象。这意味着您可以直接改变草稿对象而不会引起任何问题,因为它只是草稿而不是真正的state.

这也意味着当您尝试检查之前的状态时,它的行为会很奇怪,因为它只是草稿而不是您期望的实际对象。

如果你想要console.log一个草稿值,你可以通过console.log(current(value))使用 immercurrent函数调用来实现,该函数包含在 redux 工具包包中。(根据@markerikson 的评论进行编辑)。

至于检查每个操作对您的状态所做的更改,我建议使用Redux DevTools我能够查看调度了哪些操作、当前状态、进行了哪些更改等。 Redux 开发者工具截图

您只能引用当前切片状态。

因此,您唯一的选择是将所需的entities操作作为操作传递payload或将此操作实现为 thunkcreateAsyncThunkgetState()从其 API 中使用

我只是复制/粘贴@Linda Paiste 的 CodeSandbox 解决方案的等效项,因此查找和重用速度更快。

const usersSlice = createSlice({
  name: "users",
  initialState: {
   users: [],
  },
  reducers: {
    userCreated: (state, action) => {
      const newUser = action.payload;
      const existingUsers = JSON.parse(JSON.stringify(state.users));
      const newUsers = [...existingUsers, newUser];
      state.users= newUsers;
    }
  }
});