React 出现Cannot add property zIndex, object is not extensible

为什么在render中使用变量,会却出现了对象不可扩展。

首先,定义变量。(以下步骤全在class内部执行)

boxOpenStyle={};

然后,在方法open中去增加一个属性。

open(){
    this.boxOpenStyle.zIndex=9;
    this.setState({visible:true});
}

在方法close中对该变量重新赋值。

close(){
    this.boxOpenStyle.zIndex=8;
    this.setState({visible:false});
}

最后,render中使用该变量。

render(){
    return (
        <div style={this.state.visible ? this.boxOpenStyle:{}}></div>
    );
}

最后出现结果是:

   1.当执行open方法时,程序正常运行。
   2.当close方法被执行时,程序出错,告知对象只读,不可重新赋值。

如下图:
image.png

就算将boxOpenStyle放在state里面去改变,仍然会出现这样的错误。
但是如果将style变成id或className:

<div id={this.state.visible ? this.boxOpenStyle:{}}></div>
或
<div className={this.state.visible ? this.boxOpenStyle:{}}></div>

就不会出现这样的错误。
所以,请问这是react的什么机制触发了只读和不可扩展属性?

阅读 12.7k
2 个回答

为了避免一些错误,react内部冻结了元素的很多内容,意思就是让你尽量使用setState来更改数据。

执行open方法时,boxOpenStyle还没冻结,close的时候元素创建完成,对象已经被冻结,再更改属性抛出错误

image.png

原因:
React除了不建议props对象作为可修改对象外,还不建议把传给style属性的对象作为可修改对象。并且从React 16开始也传给style属性的对象冻结了(Object.freeze

if (propKey === STYLE) {
      if (__DEV__) {
        if (nextProp) {
          // Freeze the next style object so that we can assume it won't be
          // mutated. We have already warned for this in the past.
          Object.freeze(nextProp);
        }
      }

你的代码又是在严格模式下执行的,所以当close方法被执行时就抛TypeError异常了。

解决方案之一:

render(){
    return (
        <div style={{...(this.state.visible ? this.boxOpenStyle:{})}}></div>
    );
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题