事件处理:基于功能的组件与基于类的组件

时间:2019-02-16 21:53:47

标签: javascript reactjs event-handling components

这是我的第一个React App(react@16.8.1 )。我试图找出为什么在使用基于功能的组件与基于类的组件时onClick事件的处理方式不同。

据我所知,我应该使用基于类的c。只有当我需要更改状态时,对吗?

基于功能的组件会抛出_this is undefined error但基于类-不会。

在两种情况下,我都使用箭头功能而不是绑定功能。

基于功能:

import React from 'react';

const AnswersDisplay = (props) => {
// even with bind I still get "_this is undefined"
//this.onAnswer = this.onAnswer.bind(this); 

  const answerList = props.answerList.map( (option) => {
    return (
      <button
        onClick={this.onAnswer}
        value={option}
        className="ui basic green button">{option}
      </button>
    )
  }); 

  const onAnswer = (e) =>{
    console.log(e.target.value);
  }

  return(
    <div className="ui two buttons hSpace">{this.answerList}</div>
  );
};

export default AnswersDisplay;

vs基于类的作品。

import React from 'react';

class AnswersDisplay extends React.Component {
  constructor(props) {
    super(props);
    //this.onAnswer = this.onAnswer.bind(this);
  }

  answerList = this.props.answerList.map( (option) => {
    return (
      <button
        onClick={this.onAnswer}
        value={option}
        className="ui basic green button">{option}
      </button>
    )
  });

  onAnswer = (e) =>{
    console.log(e.target.value);
  }

  render() {
    return(
        <div className="ui two buttons hSpace">{this.answerList}</div>
    );
  }
};


export default AnswersDisplay;

2 个答案:

答案 0 :(得分:0)

对于功能组件,您要声明一个常量,并在其中保留一个函数。单击按钮时要呼叫的对象。但是,请确保在函数中使用this。在这种情况下,this将引用全局执行上下文,并且在该特定上下文中,JavaScript引擎将无法找到属性onAnswer,因此它将返回undefined

为使这项工作有效,您不带this就回叫了。

  

喜欢:onClick={onAnswer}

整个代码如下:

import React from 'react';

const AnswersDisplay = (props) => {
// even with bind I still get "_this is undefined"
//this.onAnswer = this.onAnswer.bind(this); 

  const answerList = props.answerList.map( (option) => {
    return (
      <button
        onClick={onAnswer}
        value={option}
        className="ui basic green button">{option}
      </button>
    )
  }); 

  const onAnswer = (e) =>{
    console.log(e.target.value);
  }

  return(
    <div className="ui two buttons hSpace">{this.answerList}</div>
  );
};

答案 1 :(得分:0)

MDN web doc涵盖了您需要了解的有关this的所有信息。

为简单起见,请考虑objects,其中this是“未定义”的,除非:

  • 方法/函数已与ES5的object绑定到bind(this)(请参见下面的注释),或者通过将外部函数与object重新绑定而在object之外反弹。本身:bind(obj)

注意:如下所示(在method6中),有一个例外,即在arrow functions中使用ES5 object意味着它将保留封闭的词法范围{ 1}},无需约束。

例如:

this

关于this.prop = "global prop" const outsideArrowFunction = () => (this.prop) function outsideFunction() { return this.prop; }; const obj = { prop: "obj's prop", method: function() { return this.prop; // returns "obj's prop" }, method2: function() { return this; // returns the entire "obj" and its properties }, method3: function() { return this.method(); // returns "obj's prop" }, method4: function() { return outsideFunction(); // returns "global prop" because the outsideFunction's lexical scope doesn't recognize the "obj"'s nor its properties }, method5: function() { return outsideArrowFunction(); // same as method4, utilizes global this }, method6: function() { const x = () => this.method(); return x(); // returns "obj's prop" because arrow functions take on "this" from the "obj" }, method7: function() { const x = function() { return this.prop; }; return x(); // returns "global prop" because "this" loses lexical scope upon execution }, method8: function() { const x = this.method.bind(this); return x(); // returns "obj's prop" because "this" refers to the "obj" upon execution }, method9: function(callback) { return callback(this.method); }, method10: function() { return this.method9(function(callback) { return callback(); // returns "global prop" because "this" loses lexical scope upon execution }); } }; const a = outsideArrowFunction.bind(obj); // returns "global prop" because arrow functions take on whatever "this" is upon its creation, so "this" refers to the global "this" const b = outsideFunction.bind(obj); // returns "obj's prop" since a traditional function can rebind "this", which has been rebound to "obj" console.log(`Method: ${obj.method()}`); console.log(`Method2: ${obj.method2()}`); console.log(`Method3: ${obj.method3()}`); console.log(`Method4: ${obj.method4()}`); console.log(`Method5: ${obj.method5()}`); console.log(`Method6: ${obj.method6()}`); console.log(`Method7: ${obj.method7()}`); console.log(`Method8: ${obj.method8()}`); console.log(`Method10: ${obj.method10()}`); console.log(`arrowFunction: ${a()}`); console.log(`outsideFunction: ${b()}`);,它们是classes的模板。因此,除非类objects已绑定在this中或您使用undefined,否则this将是method或是全局constructor。通过单击每个按钮来尝试下面的示例,请注意所有三种方法如何如何工作,但它取决于它们的调用方式

arrow function
class Example extends React.Component {
  constructor() {
    super();
    this.state = { method: "" };
    this.boundMethod = this.boundMethod.bind(this);
  }

  componentDidMount() { 
    this.unboundMethod(); 
  };

  boundMethod() {
    this.setState({ method: "Bound Method" }); // this works because the method is bound to the class
  }

  unboundMethod() {
    try {
      this.setState({ method: "Unbound Method" }); // this only works if it's called within a bound method class (like componentDidMount)
    } catch (err) {
      alert(err); // however, if it's called within a callback (like in an onClick event), it fails.
    }
  }

  arrowMethod = () => {
    this.setState({ method: "Arrow Method" }); // this works because arrow methods are automatically bound to the class
  };

  render() {
    return (
      <div>
        <button onClick={this.boundMethod}>Bound Method</button>
        <button onClick={this.unboundMethod}>Unbound Method</button>
        <button onClick={this.arrowMethod}>Arrow Method</button>
        <p>The {this.state.method} was called</p>
     </div>
    );
  };
}

ReactDOM.render(<Example />, document.body);