我不确定为什么我的化简代码中有Error: Immer drafts cannot have computed properties
。我正在使用redux-starter-kit
,它将所有的reducer代码包装在Immer库中。
我不完全确定Immer指的是“计算属性”。这是否意味着吸气剂/设置剂?因为我没有显式创建任何getter或setter。对象传播算子是这样做的吗?
获取器/设置器是否以某种方式污染了状态对象?
还是计算属性引用了计算属性名称? 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;
首先触发资产/初始化动作而不会发生错误,并且触发资产/上传动作时会发生沉入错误
我不确定所有获取名称/设置名称,获取uri /设置uri字段的来源。那是Immer抱怨的吗?
我重写了上载减速器以创建一个新对象
upload: (state, action) => {
const {name} = action.payload;
state.byName[name] = {
...state.byName[name],
status: 'uploading',
};
},
现在我得到的错误同样令人困惑:
答案 0 :(得分:-1)
我不确定所有获取名称/设置名称,获取uri /设置uri字段的来源。那是Immer抱怨的吗?
这些“字段”来自Redux,是的,这就是Immer抱怨的地方。它们被称为Acessors-但大多被称为Getter和Setter-在ES5中引入。这是Redux设计的使用状态的方式,即通过这些功能对对象进行变异并跟踪更改-减速器成为设置器,选择器变为获取器。现在,Immer的方法是提供一个不变的状态树,在每次状态更改时提供一个新对象。
Immer抱怨这些Acessor,因为无法可靠地克隆具有100%函数的对象,因为这些对象可能正在通过闭包访问词法范围的私有变量,即这些函数主体的变量引用将指向先前的状态(更多信息在"how do javascript closures work"上)。这不是特定于Immer的问题,而是有关JavaScript结构化克隆算法如何工作的规范。根据MDN对the structured clone algorithm的评论:
结构化克隆算法是HTML5规范定义的用于复制复杂JavaScript对象的算法。 (...)
不适用于结构化cloneSection
- 错误和功能对象不能由结构化克隆算法复制;尝试这样做将引发DATA_CLONE_ERR异常。
- 尝试克隆DOM节点同样会引发DATA_CLONE_ERR异常。
- 某些对象的参数未保留:
- 不保留RegExp对象的lastIndex字段。
- 属性描述符,设置器和获取器(以及类似的类似元数据的功能)不会重复。例如,如果使用属性描述符将对象标记为只读,则该对象将在重复对象中被读写,因为这是默认条件。
- 原型链不会被复制。
请注意,如果您使用<template>
<div class='card'>
<div class='tabs 2-col'>
<span :class="{active : view != 'signup'}" @click="view = 'login'">
Login
</span>
<span :class="{active : view == 'signup'}" @click="view = 'signup'">
Sign Up
</span>
</div>
<div class='card-body'>
<form v-show="view == 'login'" v-on:keydown.enter="login" novalidate>
<!-- my other html -->
<button @click.prevent="login">Login</button>
</form>
<form v-show="view == 'signup'" v-on:keydown.enter="signup" novalidate>
<!-- my other html -->
<button @click.prevent="signup">Sign Up</button>
</form>
</div>
</div>
</template>
<script>
export default {
data : function(){
return { view : 'login'};
},
methods : {
login: function(){
// my functionality
},
signup:function(){
// my functionality
},
}
}
</script>
将原型计算的属性名称设置为“可浸入”,则Immer可以使用原型计算的属性名称,但这不是这种情况。