首页 > 解决方案 > redux-toolkit createSlice 可以使用 js Map 作为状态吗?

问题描述

通常,强烈建议不要使用诸如此类的可变Map对象。

然而,immer的魔力允许不可变对象被操纵,就好像它们是可变的一样。

具体来说,immer 使用enableMapSet支持不可变版本的 Map

在 redux-toolkit中createReducercreateSlice使用 immer 的produce.

总的来说,我认为这些事实意味着这样的代码应该是安全的:

import { createSlice } from '@reduxjs/toolkit'

export const testmapSlice = createSlice({
  name: 'testMap',
  // Using a Map() as redux state
  initialState: new Map(),
  reducers: {
    add: (state, action) => {
      state.set(action.payload.identity, action.payload)
    },
  },
})

但是,当我在 React 组件中使用它时,我会收到礼貌的错误消息A non-serializable value was detected in the state, in the path: `testMap`. Value: Map(1) {"A" => {…}} Take a look at the reducer(s) handling this action type: testMap/add.

有没有办法安全使用Map而不会收到此错误消息?

标签: reduxredux-toolkitimmer.js

解决方案


定义“安全”:)

理论上,你可以任何你想要的东西放入 Redux 商店。

实际上,根据该常见问题解答,不可序列化的值可能会导致 DevTools 之类的东西崩溃(这首先违背了使用 Redux 的大部分目的)。使用Maps 和其他可变实例也可能导致部分 UI 无法正确重新渲染,因为 React-Redux 依赖于引用检查来确定数据是否已更改。所以,我们特别告诉用户,你永远不应该将不可序列化的值放在 Redux state中。

在这种特殊情况下,您应该能够使用一个普通的 JS 对象作为查找表而不是 a Map,并完成相同的行为。

作为绝对的最后手段,您可以关闭对 state 某些部分的序列化检查,但我们强烈不鼓励人们这样做。


推荐阅读