问题描述
我不确定为什么我的化简代码中出现了Error: Immer drafts cannot have computed properties
.我正在使用redux-starter-kit
,它使用Immer库包装了我所有的reducer代码.
Im not sure why I'm getting Error: Immer drafts cannot have computed properties
in my reducer code. I'm using redux-starter-kit
which wraps all my reducer code with the Immer library.
我不太确定Immer指的是计算属性".这是否意味着吸气剂/设置剂?因为我没有明确创建任何getter或setter.对象传播运算符是否正在执行此操作?
I'm not entirely sure what Immer is referring to with "computed property." Does it mean getters/setters? Because I'm not creating any getters or setters explicitly. Is the object spread operator doing it?
获取器/设置器是否以某种方式污染了状态对象?
Do getters/setters contaminate the state object somehow?
还是计算属性引用了计算属性名称? https://tylermcginnis.com/computed-property-names/
Or is computed property in reference to computed property names? https://tylermcginnis.com/computed-property-names/
我的减速器非常简单:
import { createSlice } from 'redux-starter-kit'
const assets = createSlice({
slice: 'assets',
initialState: {byName: {}},
reducers: {
upload: (state, action) => {
const {name} = action.payload;
state.byName[name].status = 'uploading';
},
initialize: (state, action) => {
const {assets, id} = action.payload;
assets.forEach(({name, uri}) => {
state.byName[name] = {
uri,
name,
status: 'local',
id,
inProgress: true
};
});
},
}
})
export default assets;
首先触发资产/初始化动作而不会发生错误,并且在触发资产/上传动作时会发生沉入错误
The assets/initialize action is triggered first with no error, and the immer error occurs when the assets/upload action is triggered
我不确定所有获取名称/设置名称,获取uri/设置uri字段的来源.这是Immer抱怨的吗?
I'm not sure where all those get name / set name, get uri / set uri fields are coming from. Is that what Immer is complaining about?
我重写了上载减速器以创建一个新对象
I rewrote the upload reducer to create a new object,
upload: (state, action) => {
const {name} = action.payload;
state.byName[name] = {
...state.byName[name],
status: 'uploading',
};
},
我现在得到的错误同样令人困惑:
and the error I get now is equally baffling:
推荐答案
这些字段"来自Redux,是的,这就是Immer抱怨的地方.它们被称为Acessors-但大多被称为Getter和Setter-它们是在ES5中引入的.这是Redux设计的状态处理方式,即通过这些功能对对象进行突变并跟踪更改-减速器变成了setter,选择器变成了getter.现在,Immer的方法是提供一个不变的状态树,在每次状态更改时都提供一个新对象.
These "fields" come from Redux, and yes, that's what Immer is complaining about. They're called Acessors - but mostly known as Getter and Setter - which were introduced in ES5. This is by design Redux's way to work with state, which is to mutate the object and track changes through these functions - your reducers become setters, and selectors become getters. Now Immer's approach is to provide an immutable state tree, providing a new object on every state change.
Immer抱怨这些Acessor,因为无法可靠地克隆具有100%功能的对象,因为这些对象可能正在通过闭包访问词法范围的私有变量,即这些函数体的变量引用将指向先前的状态(更多信息在"javascript闭包如何工作" )上.这不是特定于Immer的问题,而是有关JavaScript结构化克隆算法如何工作的规范.根据MDN对结构化克隆算法的评论:
Immer complains about these acessors because there's no way to clone object with functions 100% reliably, as these may be accessing lexically-scoped private variables through closures, i.e. these function bodies variable references would point to the previous state (more on that on "how do javascript closures work"). And this isn't an Immer-specific problem, it is the very specification of how the JavaScript structured clone algorithm work. As per MDN comment on the structured clone algorithm:
- 错误和功能对象不能由结构化克隆算法复制;尝试这样做将引发DATA_CLONE_ERR异常.
- 尝试克隆DOM节点同样会引发DATA_CLONE_ERR异常.
- 某些对象的参数未保留:
- 不保留RegExp对象的lastIndex字段.
- 属性描述符,设置器和获取器(以及类似的类似元数据的功能)不会重复.例如,如果使用属性描述符将对象标记为只读,则该对象将在重复对象中被读写,因为这是默认条件.
- 原型链不会被复制.
- Error and Function objects cannot be duplicated by the structured clone algorithm; attempting to do so will throw a DATA_CLONE_ERR exception.
- Attempting to clone DOM nodes will likewise throw a DATA_CLONE_ERR exception.
- Certain parameters of objects are not preserved:
- The lastIndex field of RegExp objects is not preserved.
- Property descriptors, setters, and getters (as well as similar metadata-like features) are not duplicated. For example, if an object is marked read-only using a property descriptor, it will be read-write in the duplicate, since that's the default condition.
- The prototype chain does not get walked and duplicated.
请注意,如果将
prototype[immerable] = true
设置为可浸入式",则原型计算的属性名称可与Immer一起使用,但这不是这种情况.Note that prototype computed property names do work with Immer if you set it as "immerable" with
prototype[immerable] = true
, but that's not the case here.这篇关于沉浸式草稿,计算属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!