无法在事件处理程序中访问React实例(此)

启人 · 05月25日

我正在用ES6(使用BabelJS)编写一个简单的组件,并且功能this.setState无法正常工作。

典型的错误包括类似

无法读取未定义的属性“ setState”

要么

this.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
回答(10)
时间
阿飞村村
10 · 2020-05-25 12:02:49

亚力山大·柯森伯格(Alexandre Kirszenberg)是对的,但是要注意的另一件重要的事情是放置约束。我已经被这种情况困扰了好几天(可能是因为我是一个初学者),但是与其他人不同,我知道bind(我已经申请过),所以我无法理解为什么我仍然会遇到这种情况错误。原来,我的装订顺序错误。

另一个可能是我在“ this.state”中调用函数的事实,该函数不知道绑定,因为它恰好位于绑定线上方,

以下是我所拥有的(顺便说一句,这是我的第一个帖子,但是我认为这非常重要,因为在其他任何地方都找不到解决方案):

constructor(props){
    super(props);

       productArray=//some array

    this.state={ 
        // Create an Array  which will hold components to be displayed
        proListing:productArray.map(product=>{return(<ProRow dele={this.this.popRow()} prodName={product.name} prodPrice={product.price}/>)})
    }

    this.popRow=this.popRow.bind(this);//This was the Issue, This line //should be kept above "this.state"
飞云
9 · 2020-05-25 12:02:48

您的函数需要绑定才能与事件处理程序中的状态或道具一起玩

在ES5中,仅将事件处理程序函数绑定在构造函数中,而不直接在render中绑定。如果您确实直接在render中绑定,那么每次您的组件渲染并重新渲染时,它都会创建一个新函数。因此,您应始终将其绑定到构造函数中

this.sendContent = this.sendContent.bind(this)

在ES6中,使用箭头功能

使用箭头功能时,无需绑定,也可以避免与范围相关的问题

sendContent = (event) => {

}
仲羽
8 · 2020-05-25 12:02:48

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

constructor(props) {
  super(props);
  this.changeContent = this.changeContent.bind(this);
}
伽罗
7 · 2020-05-25 12:02:48

此问题在react15.0之后发生,该事件处理程序未自动绑定到组件。因此,无论何时调用事件处理程序,都必须手动将其绑定到组件。


解决问题有几种方法。但是您需要知道哪种方法最好,为什么?通常,我们建议在类构造函数中绑定函数或使用箭头函数。

// method 1: use a arrow function
    class ComponentA extends React.Component {
      eventHandler = () => {
        console.log(this)
      }
      render() {
        return ( 
        <ChildComponent onClick={this.eventHandler} /> 
        );
      }

// method 2: Bind your functions in the class constructor.
    class ComponentA extends React.Component {
      constructor(props) {
        super(props);
        this.eventHandler = this.eventHandler.bind(this);
      }
      render() {
        return ( 
        <ChildComponent onClick={this.eventHandler} /> 
        );
      }

组件每次渲染时,这两种方法将不会创建新函数。因此我们的ChildComponent不会因为新功能道具的更改而重新渲染,否则可能会产生性能问题。

西
西里神奇
6 · 2020-05-25 12:02:48

如果要使绑定保持构造函数语法,则可以使用proposal-bind-operator并转换代码,如下所示:

constructor() {
  this.changeContent = ::this.changeContent;
}

代替 :

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

简单得多,不需要bind(this)fatArrow

猿乐
5 · 2020-05-25 12:02:48

如果有人能得到这个答案,这是一种绑定所有功能而无需手动绑定它们的方法

在constructor()中:

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

或在global.jsx文件中创建此函数

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

并在您的constructor()中将其调用为:

bindAllFunctions({ bindTo: this })
宝儿理查德
4 · 2020-05-25 12:02:48

发生此问题的原因是,this.changeContent并且onClick={this.sendContent}不限于此组件实例的实例。

还有另一种解决方案(除了使用bind()的构造函数())使用共享周围的代码相同词法范围ES6的箭头功能,并保持这个,所以你可以改变在渲染(你的代码)是:

render() {
    return (

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

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

    )
  }
樱小胖Mandy
3 · 2020-05-25 12:02:48

我们必须对bind函数进行操作,this以获取类中函数的实例。像这样

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

这种方式this.state将是有效的对象。

T
Tony凯
2 · 2020-05-25 12:02:48

我的建议是使用箭头函数作为属性

class SomeClass extends React.Component {
  handleClick = () => {
    console.log(this); // the React Component instance
  }
  render() {
    return (
      <button onClick={this.handleClick}></button>
    );
  }
}

并且不要将箭头功能用作

class SomeClass extends React.Component {
      handleClick(){
        console.log(this); // the React Component instance
      }
      render() {
        return (
          <button onClick={()=>{this.handleClick}}></button>
        );
      }
    }

因为第二种方法实际上将在每个渲染调用中生成新函数,实际上这意味着新版本的props指针,而不是如果您以后要关心性能,则可以使用React.PureComponent或在React.Component中, 您可以覆盖shouldComponentUpdate(nextProps,nextState)并在道具到达时进行浅层检查

番长
1 · 2020-05-25 12:02:48

this.changeContentthis.changeContent.bind(this)在作为onChangeprop 传递之前,需要先通过绑定到组件实例,否则this函数主体中的变量将不会引用组件实例,而会引用window参见Function :: bind

当使用React.createClass而不是ES6类时,在组件上定义的每个非生命周期方法都将自动绑定到组件实例。请参阅自动绑定

请注意,绑定功能会创建一个新功能。您可以将其直接绑定到render中,这意味着每次渲染该组件时都会创建一个新函数,或者将其绑定到构造函数中,后者只会触发一次。

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

render() {
  return <input onChange={this.changeContent.bind(this)} />;
}

引用是在组件实例上设置的,而不是在实例上设置的React.refs:您需要更改React.refs.somerefthis.refs.someref您还需要将sendContent方法绑定到组件实例,以便对其进行this引用。

你的回答

加载中...
⌘+Return 发表
发表

温馨提示:登录后可发表评论或回复

关闭,朕知道了

扫码关注微信公众号或小程序