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

Posted

技术标签:

【中文标题】如何在 createSlice 的 reducer 中获取状态值?【英文标题】:How can I get the state value in the reducer of createSlice? 【发布时间】:2021-01-01 05:23:37 【问题描述】:

我在我的 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 创建的 code sandbox 工作正常,这意味着我们可以访问 reducer 中的状态变量,但我们无法调试状态变量以更深入地挖掘该状态变量目前持有的内容,因为Redux-toolkit 正在以自己的方式处理状态...... 从调试截图中可以明显看出

【问题讨论】:

我今天会尝试创建一个代码沙箱并在此处链接。 @karlmarxlopez 仍在等待您的输入 :) codesandbox.io/s/boring-nightingale-frp6b?file=/src/reducer.ts 它说赏金有 15 小时的宽限期。但我不清楚你想要实现什么。只是为了更好地调试吗?您可以使用 Redux DevTools 扩展名,这似乎对我有用。我按照@karlmaxlopex 的建议查看了 Immer 文档,this page 解释了先前的状态如何是“草稿”而不是实际对象。所以你不能 console.log 它但是有一个通过 JSON 的解决方法。 【参考方案1】:

从我自己和@karlmaxlopez 总结 cmets 中的信息:

我将您的代码复制到CodeSandbox demo 中,发现代码确实按预期执行。即使state.entities 的值在检查时显示为Proxy 或在记录时显示为null,您也可以将其附加到state.entities 数组。

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

但是 redux-toolkit 和 Immer 为如何编写 reducer 提供了额外的可能性。在Immer reducer 中,函数接收的state 参数是“草稿”对象。这意味着您可以直接改变草稿对象而不会导致任何问题,因为它只是草稿而不是真正的state

这也意味着当你尝试检查这个先前的状态时,它会表现得很奇怪,因为它只是一个草稿,而不是你所期望的实际对象。

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

就检查每个操作对您的状态所做的更改而言,我建议使用Redux DevTools。我能够看到发送了哪些操作、当前状态、进行了哪些更改等。

【讨论】:

感谢您的意见。我还有 5 个小时来奖励赏金 :) 我已经在使用 Redux DevTools。实际上,我期待通过应用存储冻结策略来控制重新创建状态,就像我们在 Angular 中所做的那样:) 我认为我们应该在 createSlice 中设置标志(开/关)来控制我们将如何改变状态 正确答案在这里,虽然我建议使用the Immer current API exported from RTK而不是JSON.stringify()【参考方案2】:

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

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

【讨论】:

我可以使用 Redux Reducer 来实现目标吗?我的意思是,我能在 Redux reducer 中获取状态变量吗? 是的,参考文档redux.js.org/basics/reducers【参考方案3】:

我只是复制/粘贴 @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;
    
  
);

【讨论】:

以上是关于如何在 createSlice 的 reducer 中获取状态值?的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

有没有办法在 createSlice 中访问全局状态?

如何在没有 createSlice 的情况下使用 createThunkAsync

是否可以使用 Redux Toolkit 从另一个 reducer 函数(在同一切片内)调用 reducer 函数?