【问题标题】:Can a redux-toolkit createSlice use a js Map as state?redux-toolkit createSlice 可以使用 js Map 作为状态吗?
【发布时间】:2020-11-12 04:35:24
【问题描述】:

一般来说,使用可变对象如Map就是strongly discouraged

然而,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 而不会收到此错误消息?

【问题讨论】:

    标签: redux redux-toolkit immer.js


    【解决方案1】:

    定义“安全”:)

    理论上,您可以任何东西放入 Redux 存储中。

    实际上,根据该常见问题解答,不可序列化的值可能会导致 DevTools 之类的东西崩溃(这首先违背了使用 Redux 的大部分目的)。使用Maps 和其他可变实例也可能导致部分 UI 无法正确重新渲染,因为 React-Redux 依赖于引用检查来确定数据是否已更改。所以,we specifically tell users that you should never put non-serializable values in the Redux state

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

    作为绝对的最后手段,您可以turn off the serialization checking for certain parts of the state,但我们强烈反对人们这样做。

    【讨论】:

    • 我特别好奇 immer 是否会改变任何东西。如果我使用的是 immutableJS,我可以将初始值设置为 Map 并知道它是不可变的并且 redux 很高兴。但是由于 immer 是 redux-toolkit 默认的,我想知道是否有办法告诉 redux,在初始状态下“这是被 immer 冻结的”。对于我的用例,map的插入顺序迭代是可取的,但是键的数量很少,所以我可能会使用数组来代替。
    • Tbh 我不知道 Immer 如何实现对更新 Maps 的支持。我的假设是它不会复制地图,如果您尝试在 UI 中读取state => state.some.map,这将导致错误 - 它永远不会知道重新渲染。请注意 JS 对象 do mostly use insertion order for iteration of string keys,这可能足以满足您的目的。
    【解决方案2】:

    我认为在 state 上使用 Map() 是不安全的,因为 Redux 已经被设计为避免在 Reducers 级别的突变,并且当您使用 createSlice() 时,它甚至会在后台处理它。您对州级双重安全的想法似乎是您引发的另一个问题。它可能会导致 UI 不更新。或抛出错误 (ps:这个纯属类比,我没试过)

    【讨论】:

      猜你喜欢
      • 2020-07-14
      • 2021-04-14
      • 1970-01-01
      • 2022-09-26
      • 2020-04-12
      • 2020-12-14
      • 2020-03-01
      • 2022-06-22
      相关资源
      最近更新 更多