为什么在类构造函数中使用setState方法时React会抛出错误?

为什么在类构造函数中使用setState方法时React会抛出错误?

问题描述:

我知道为尚未挂载的组件设置状态时会引发错误。这解释了我使用setState函数而不是明确地直接设置状态所产生的错误。

I know that an error is thrown when setting state for a component not yet mounted. Which explains the error I get from using setState function as oppose to explicitly and directly setting the state.

import React, {Component} from 'react';

class SearchBar extends Component {

constructor(props) {
  super(props);

  this.state = {term: ''}; // -> seems to be the agreed means to set   initial state
// this.setState({term: ''}); // -> generates an error
}

render() {
  return (
    <div>
      <input onChange={event => this.setState({term:   event.target.value})}/>
      Value of the input: {this.state.term}
  </div>
);
  }
}




我得到的错误当我取消注释第二行时,this.setState({term:''})是:

The error I get when I uncomment the second line this.setState({term: ''}) is:

警告:setState(...) :只能更新已安装或安装的组件。这通常意味着您在已卸载的组件上调用了setState()。这是一个无操作。请检查组件的代码。

Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the component.

我知道如何防止错误,只需明确设置状态而不告诉React有关它的任何内容我已经看过github问题谈论这个bug: Github Issue#3878 我想知道的是为什么不能反应搞定了吗?如果从构造函数中调用setState,它知道这是第一次使用它吗?我可能太简单了,但如果有人有一个很好的技术答案,为什么不呢?

I know how to prevent the error, simply by setting state explicitly without telling React anything about it and I have already seen the github issue talking about the bug: Github Issue #3878 What I want to know though is why cant React work it out? if one calls setState from a constructor it knows this is the first time its being used? I am probably simplifying it way too much, but if anyone has a nice technical answer as the reason why not?

React类始终使用名为 state 的属性进行初始化值 null ,如源代码。如您所知,React提供了一个 setState 方法来操作此属性。根据文档

React classes have always initialized with a property called state set to a value of null as seen in the source code. As you know, React provides a setState method for manipulating this property. According to the docs:


setState()不会立即改变this.state但会创建挂起状态转换。在调用此方法后访问this.state可能会返回现有值。

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

无法保证对setState的调用同步操作,并且可以对调用进行批处理以提高性能。

There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.

除非在shouldComponentUpdate()中实现条件渲染逻辑,否则setState()将始终触发重新渲染。

setState() will always trigger a re-render unless conditional rendering logic is implemented in shouldComponentUpdate().

简而言之, setState()是一个异步的,多步骤,不可预测的操作,会导致组件重新出现。要调用这样的函数,需要一个对象已经完全初始化,因此在类仍在挂载时不会发生。在完全初始化之前,它已经尝试在类上执行生命周期操作。

In short, setState() is an asynchronous, multi-step, unpredictable operation that will cause component rerenders. To call such a function would require an object to already be fully initialized and thus couldn't happen while the class is still mounting. It would already try to perform lifecycle operations on the class before it was fully initialized.

当然,如果您希望组件以状态开始,则会出现问题这不是 null 但又不想立即导致多次渲染和操作。这就是为什么React提供了一种初始化组件状态而不依赖于 setState 的方法。在ES5中,这是在名为 getInitialState 的属性中设置初始状态。但是,当使用特殊的构造函数方法(因此React不再需要自己的自定义版本)。这就是为什么,如果你想在安装时用一个状态初始化一个React组件,你必须将它声明为 this.state = {} 而不是使用 setState()

Of course, that leaves an issue if you want a component to start out with a state that is not null and yet don't want to immediately cause multiple renders and operations to take place. That is why React provides a way to initialize a component state without relying on setState. In ES5, this was setting the initial state inside of a property called getInitialState. However, ES6 introduced a native syntax for setting properties when a class is initialized with a special constructor method (so React no longer had need of its own custom version). That is why, if you want to initialize a React component with a state when it is mounting, you must declare it as this.state = {} and not use setState().