沉浸的草稿,计算的属性

时间:2019-08-15 05:46:33

标签: javascript redux immer.js

我不确定为什么我的化简代码中有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;

首先触发资产/初始化动作而不会发生错误,并且触发资产/上传动作时会发生沉入错误

assets/initialize output

我不确定所有获取名称/设置名称,获取uri /设置uri字段的来源。那是Immer抱怨的吗?

assets/upload output

我重写了上载减速器以创建一个新对象

upload: (state, action) => {
    const {name} = action.payload;
    state.byName[name] = {
        ...state.byName[name],
        status: 'uploading',
    };
},

现在我得到的错误同样令人困惑:

assets/upload error output

1 个答案:

答案 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可以使用原型计算的属性名称,但这不是这种情况。