当前位置: 首页 > 知识库问答 >
问题:

无法访问事件处理程序[重复]内部的React实例(this)

吴升
2023-03-14

我正在用ES6编写一个简单的组件(使用BabelJS),函数this.setstate不工作。

典型的错误包括

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

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

共有3个答案

辛锦
2023-03-14

当从react.createClass()组件html" target="_blank">定义语法过渡到扩展react.component的ES6类方式时,这个问题是我们大多数人首先经历的事情之一。

它是由react.createClass()extends react.component中的this上下文差异引起的。

使用react.createClass()会自动正确绑定this上下文(值),但使用ES6类时并非如此。当使用ES6方法(通过扩展react.component)时,this上下文默认为null。类的属性不会自动绑定到React类(组件)实例。

我总共知道4种通用方法。

>

  • 在类构造函数中绑定函数。许多人认为这是一种最佳实践方法,它完全避免接触JSX,并且不会在每个组件重新呈现时创建新的函数。

    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>
        );
      }
    }
    

    将函数内联绑定。您仍然可以在一些教程/文章/等等中找到这种方法,所以了解它是很重要的。它的概念与#1相同,但要注意,绑定一个函数会在每次重新呈现时创建一个新函数。

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

    使用胖箭头函数。在箭头函数之前,每个新函数都定义了自己的this值。但是,arrow函数并不创建自己的this上下文,因此this具有来自React组件实例的原始含义。因此,我们可以:

    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>
        );
      }
    }
    

    使用实用函数库自动绑定函数。有一些实用程序库可以自动为您完成这项工作。下面是一些流行的,只提几个:

    >

  • autobind Decorator是一个NPM包,它将类的方法绑定到this的正确实例,即使方法被分离时也是如此。包使用@autobindbefore方法将this绑定到对组件上下文的正确引用。

    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装饰器足够聪明,可以让我们一次绑定组件类中的所有方法,就像方法#1一样。

    类Autobind是另一个被广泛用于解决此绑定问题的NPM包。与Autobind Decorator不同,它不使用Decorator模式,而实际上只是在构造函数中使用一个函数,该函数自动将组件的方法绑定到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>
        );
      }
    }
    

    附注:其他非常相似的库是React Autobind。

    如果我是你,我会坚持第一条。但是,一旦在类构造函数中得到大量绑定,我将建议您探索方法#4中提到的一个帮助器库。

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

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

    出于类似的目的,就像您需要的那样,使用受控组件是首选的方式。我建议您考虑使用组件state。因此,您可以简单地访问值,如下所示:this.state.inputContent

  • 鲜于承基
    2023-03-14

    Morhaus是正确的,但这可以在没有bind的情况下解决。

    您可以将箭头函数与类属性建议一起使用:

    class SomeClass extends React.Component {
      changeContent = (e) => {
        this.setState({inputContent: e.target.value})
      } 
    
      render() {
        return <input type="text" onChange={this.changeContent} />;
      }
    }
    

    因为箭头函数是在构造函数的作用域中声明的,而且箭头函数在其声明作用域中维护this,所以它都可以工作。这里的缺点是这些将不是原型中的函数,它们都将与每个组件一起重新创建。但是,这并不是什么坏处,因为bind会导致同样的结果。

    端木涵润
    2023-03-14

    this.ChangeContent在作为OnChange道具传递之前,需要通过this.ChangeContent.bind(this)绑定到组件实例,否则函数主体中的this变量将不引用组件实例,而是引用Window。请参阅Function::Bind。

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

    请注意,绑定一个函数会创建一个新函数。您可以在render中直接绑定它,这意味着每次组件呈现时都会创建一个新函数,也可以在您的构造函数中绑定它,这只会激发一次。

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

    VS

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

    Refs是在组件实例上设置的,而不是在react.Refs上设置的:您需要将react.Refs.someRef更改为this.Refs.someRef。您还需要将sendcontent方法绑定到组件实例,以便this引用它。

     类似资料:
    • 问题内容: 我正在用ES6(使用BabelJS)编写一个简单的组件,并且功能无法正常工作。 典型的错误包括类似 无法读取未定义的属性“ setState” 要么 this.setState不是一个函数 你知道为什么吗?这是代码: 问题答案: 在作为prop 传递之前,需要先通过绑定到组件实例,否则函数主体中的变量将不会引用组件实例,而会引用。参见Function :: bind 。 当使用而不是E

    • 问题内容: 我正在用ES6(使用BabelJS)编写一个简单的组件,并且功能无法正常工作。 典型的错误包括类似 无法读取未定义的属性“ setState” 要么 this.setState不是一个函数 你知道为什么吗?这是代码: 问题答案: 在作为prop 传递之前,需要先通过绑定到组件实例,否则函数主体中的变量将不会引用组件实例,而是指向。参见Function :: bind 。 当使用而不是E

    • 我试图创建一个反应组件,这是一个文本输入。当有人按下回车键时,必须调用mymethod()。但是在handleKeyPress,我不能访问类范围。我怎样才能解决这个问题?

    • 我想在JavaFX中制作一个程序,其中包含一个按钮,单击该按钮时,将创建一个圆并将其添加到形状的ArrayList中。以下是我的代码: 我的问题是-如何从内部句柄方法访问“circle1”?在JavaScript中,我们使用e.currentTarget。 我无法声明“Circle1”最终版本,因为我需要在之后更改它。

    • 我在主页组件中有这个代码,当按下向下/向上箭头键时,什么也没有发生。我刚刚意识到,当用ctrl键按箭头键时,eventhandler可以正常工作。我到处找,但什么也没找到。有人能帮忙吗?我的浏览器是Chrome v.96。React版本17.0.2,节点v.16.13.1