无法在尚未装入的组件上调用setState

Kev*_*Kev 16 javascript reactjs mobx mobx-react

这是我第一次面对这个警告信息.

无法在尚未装入的组件上调用setState.

具体情况如下:

这是一个无操作,但它可能表示您的应用程序中存在错误.相反,this.state直接指定或state = {};在MyComponent组件中定义具有所需状态的类属性.

" 尚未安装 "部分实际上几乎没有意义,因为触发问题的唯一方法是通过单击需要安装的组件中的按钮来调用函数以查看按钮.该组件在任何给定时间都没有卸载.

这个虚拟组件在我的应用程序中重现错误:

import PropTypes from 'prop-types'
import React from 'react'

export default class MyComponent extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      initial: 'state'
    }
    this.clickMe = this.clickMe.bind(this)
  }

  clickMe () {
    this.setState({
      some: 'new state'
    })
  }

  render () {
    return (
      <div>
        <button onClick={this.clickMe}>click</button>
      </div>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

我在用:

"react": "16.3.2",
"react-dom": "16.3.2",
"mobx": "4.2.0",
"mobx-react": "5.1.2",
Run Code Online (Sandbox Code Playgroud)

我在最新的React/mobx版本中遗漏了什么吗?(注意组件不使用任何与mobx相关的东西,但它的父级是一个mobx-react观察者)

编辑:

一定有什么相关的组件实例,进一步的调查表明,在某些情况下,创建渲染功能内的处理程序将使该警告消失,但不是在所有情况下.

class MyComponent extends React.component {
  constructor (props) {
    // ...
    this.clickMeBound = this.clickMe.bind(this)
  }

  clickMe () {
    ...
  }

  render () {
    // works
    <button onClick={() => {this.clickMe()}}>click arrow in render</button>

    // warning: Can't call setState on a component that is not yet mounted.
    <button onClick={this.clickMeBound}>click bound</button>
  }
}
Run Code Online (Sandbox Code Playgroud)

编辑2:

我已经从我的Webpack配置中的条目中删除了"react-hot-loader/patch",这个奇怪的问题已经消失了.我不是把它作为答案,因为错误消息本身仍然很奇怪,这会在控制台中引发警告.一切都很好.

小智 16

您收到的这个警告是因为您在构造函数中设置了对clickMe 方法的引用,然后使用setState()

constructor (props) {
    super(props)
    this.state = {
       initial: 'state',
       some: ''          
    }
   this.clickMe = this.clickMe.bind(this);   <--- This method
  }

 clickMe () {
   this.setState({
     some: 'new state'    <-- the setState reference that is causing the issue
   })
  }
Run Code Online (Sandbox Code Playgroud)

尝试从构造函数中删除this.clickMe = this.clickMe.bind(this)并在生命周期方法中执行此操作,例如componentWillMount() 或 ComponentDidMount()。对于 react 16 及更高版本,您可以使用带有“SAFE_”前缀的componentWillMount 方法[SAFE_componentWillMount]

 componentWillMount() {
      this.clickMe = this.clickMe.bind(this);
 }

clickMe () {
   this.setState({
     some: 'new state'    
   })
  }
Run Code Online (Sandbox Code Playgroud)


Mah*_*our 7

只需将以下行添加到您的代码中

export default class MyComponent extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
       initial: 'state',
       some: ''          // <-------  THIS LINE
    }
   this.clickMe = this.clickMe.bind(this)
  }

 clickMe () {
   this.setState({
     some: 'new state'
   })
  }

 render () {
   return (
     <div>
       <button onClick={this.clickMe}>click</button>
     </div>
   );
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 你能解释一下,他为什么要这么做吗?这条线对我来说似乎有点随机? (4认同)

Var*_*tel 7

您不应该在构造函数中使用 setState,因为组件尚未安装。在这种情况下,clickMe() 方法调用 setState()。
相反,直接初始化状态。喜欢,

constructor(props) {
    super(props);
    // Don't call this.setState() here!
    this.state = { counter: 0 };
    this.handleClick = this.handleClick.bind(this);
}
Run Code Online (Sandbox Code Playgroud)

例如,如果来自https://reactjs.org/docs/react-component.html#constructor

使用 setState() 是为了让我们可以通过重新渲染来反映状态的变化。由于组件尚未渲染,我们可以直接更改状态,并且更改将反映在 render() 方法的调用上。

  • 我的示例代码已经是这样了。不管怎样,在某些情况下,这个问题是由react-hot-loader引起的,人们正在转向react-refresh。 (2认同)

小智 5

您只需要使用该componentDidMount()方法。正如 React 文档在组件生命周期中所说,如果您需要从远程端点加载数据,这是实例化网络请求的好地方,您可以setState()立即调用componentDidMount().

像这样:

componentDidMount(){
  this.clickMe = this.clickMe.bind(this);
}
clickMe () {
  this.setState({
    some: 'new state'
  })
}
Run Code Online (Sandbox Code Playgroud)