我正在ES6中编写一个简单的组件(使用BabelJS),并函数此。setState不工作。

典型的错误包括

无法读取undefined的属性“setState”

or

这一点。setState不是一个函数

你知道为什么吗?代码如下:

import React from 'react'

class SomeClass extends React.Component {
  constructor(props) {
    super(props)
    this.state = {inputContent: 'startValue'}
  }

  sendContent(e) {
    console.log('sending input content '+React.findDOMNode(React.refs.someref).value)
  }

  changeContent(e) {
    this.setState({inputContent: e.target.value})
  } 

  render() {
    return (
      <div>
        <h4>The input form is here:</h4>
        Title: 
        <input type="text" ref="someref" value={this.inputContent} 
          onChange={this.changeContent} /> 
        <button onClick={this.sendContent}>Submit</button>
      </div>
    )
  }
}

export default SomeClass

当前回答

如果有人能找到这个答案, 下面是一种无需手动绑定所有函数的方法

在构造函数()中:

for (let member of Object.getOwnPropertyNames(Object.getPrototypeOf(this))) {
    this[member] = this[member].bind(this)
}

或者在全局变量中创建这个函数。jsx文件

export function bindAllFunctions({ bindTo: dis }) {
for (let member of Object.getOwnPropertyNames(Object.getPrototypeOf(dis))) {
    dis[member] = dis[member].bind(dis)
    }
}

并在你的构造函数()调用它如下:

bindAllFunctions({ bindTo: this })

其他回答

这个问题是我们大多数人在从React.createClass()组件定义语法过渡到扩展React.Component的ES6类方式时最先经历的事情之一。

这是由React.createClass()与extends React.Component中的上下文差异引起的。

使用React.createClass()将自动正确绑定此上下文(值),但在使用ES6类时并非如此。当以ES6的方式(通过扩展React.Component)执行时,此上下文默认为空。类的属性不会自动绑定到React类(组件)实例。


解决该问题的方法

我一共知道4种一般的方法。

Bind your functions in the class constructor. Considered by many as a best-practice approach that avoids touching JSX at all and doesn't create a new function on each component re-render. class SomeClass extends React.Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick() { console.log(this); // the React Component instance } render() { return ( <button onClick={this.handleClick}></button> ); } } Bind your functions inline. You can still find this approach used here and there in some tutorials / articles / etc, so it's important you're aware of it. It it the same concept like #1, but be aware that binding a function creates a new function per each re-render. class SomeClass extends React.Component { handleClick() { console.log(this); // the React Component instance } render() { return ( <button onClick={this.handleClick.bind(this)}></button> ); } } Use a fat arrow function. Until arrow functions, every new function defined its own this value. However, the arrow function does not create its own this context, so this has the original meaning from the React component instance. Therefore, we can: class SomeClass extends React.Component { handleClick() { console.log(this); // the React Component instance } render() { return ( <button onClick={ () => this.handleClick() }></button> ); } } or class SomeClass extends React.Component { handleClick = () => { console.log(this); // the React Component instance } render() { return ( <button onClick={this.handleClick}></button> ); } } Use utility function library to automatically bind your functions. There are a few utility libraries out there, that automatically does the job for you. Here are some of the popular, just to mention a few: Autobind Decorator is an NPM package which binds methods of a class to the correct instance of this, even when the methods are detached. The package uses @autobind before methods to bind this to the correct reference to the component's context. import autobind from 'autobind-decorator'; class SomeClass extends React.Component { @autobind handleClick() { console.log(this); // the React Component instance } render() { return ( <button onClick={this.handleClick}></button> ); } } Autobind Decorator is smart enough to let us bind all methods inside a component class at once, just like approach #1. Class Autobind is another NPM package that is widely used to solve this binding issue. Unlike Autobind Decorator, it does not use of the decorator pattern, but really just uses a function inside your constructor that automatically binds the Component's methods to the correct reference of this. import autobind from 'class-autobind'; class SomeClass extends React.Component { constructor() { autobind(this); // or if you want to bind only only select functions: // autobind(this, 'handleClick'); } handleClick() { console.log(this); // the React Component instance } render() { return ( <button onClick={this.handleClick}></button> ); } } PS: Other very similar library is React Autobind.


建议

如果我是你,我会坚持第一种方法。但是,一旦您的类构造函数中有大量的绑定,我建议您研究方法#4中提到的helper库之一。


其他

这与你的问题无关,但你不应该过度使用裁判。

你的第一个倾向可能是使用refs在你的应用中“让事情发生”。如果是这种情况,花点时间,更批判性地思考在组件层次结构中应该在哪里拥有状态。

对于类似的目的,就像您需要的一样,使用受控组件是首选的方法。我建议您考虑使用Component状态。所以,你可以像这样访问这个值:this.state. inputcontent。

这个问题的发生是因为。changeContent和onClick={this。sendContent}不绑定到组件实例的this。

还有另一种解决方案(除了在构造函数()中使用bind()之外)使用ES6中的箭头函数,这些函数与周围的代码共享相同的词法范围并维护它,所以你可以在render()中更改你的代码为:

render() {
    return (

        <input type="text"
          onChange={ () => this.changeContent() } /> 

        <button onClick={ () => this.sendContent() }>Submit</button>

    )
  }

你好,如果你不想关心绑定你自己的函数调用。你可以使用'class-autobind'然后像这样导入它

import autobind from 'class-autobind';

class test extends Component {
  constructor(props){
  super(props);
  autobind(this);
}

不要在super调用之前写autobind,因为它将不起作用

您使用的是ES6,因此函数不会自动绑定到“此”上下文。您必须手动将函数绑定到上下文。

constructor(props) {
  super(props);
  this.changeContent = this.changeContent.bind(this);
}

如果有人能找到这个答案, 下面是一种无需手动绑定所有函数的方法

在构造函数()中:

for (let member of Object.getOwnPropertyNames(Object.getPrototypeOf(this))) {
    this[member] = this[member].bind(this)
}

或者在全局变量中创建这个函数。jsx文件

export function bindAllFunctions({ bindTo: dis }) {
for (let member of Object.getOwnPropertyNames(Object.getPrototypeOf(dis))) {
    dis[member] = dis[member].bind(dis)
    }
}

并在你的构造函数()调用它如下:

bindAllFunctions({ bindTo: this })