【问题标题】:How to bind onclick handlers to `this` properly on React如何在 React 上正确地将 onclick 处理程序绑定到`this`
【发布时间】:2017-06-06 18:05:07
【问题描述】:

解释为什么这不是重复的:我的代码已经在运行,我已将其作为评论包含在内。问题是为什么当我将 this 包含在单击处理函数中时上下文会发生变化。
我正在尝试在 React 中创建一个计算器项目。目标是将 onclick 处理程序附加到数字按钮,以便数字显示在计算器显示区域上。如果处理程序直接写入渲染方法,则它正在工作,但是,如果我从 ComponentDidMount 尝试,我会收到错误this.inputDigit is not a function。如何正确绑定this.inputDigit(digit)

import React from 'react';
import './App.css';

export default class Calculator extends React.Component {

// display of calculator initially zero
state = {
  displayValue: '0'
}

//click handler function
inputDigit(digit){
  const { displayValue } = this.state;
  this.setState({
    displayValue: displayValue+String(digit)
  })
}

componentDidMount(){

  //Get all number keys and attach click handler function
  var numberKeys = document.getElementsByClassName("number-keys");
  var myFunction = function() {
    var targetNumber = Number(this.innerHTML);
    return this.inputDigit(targetNumber); // This is not working
  };
  for (var i = 0; i < numberKeys.length; i++) {
    numberKeys[i].onclick = myFunction;
  }

}

render() {
  const { displayValue } = this.state;
  return (
    <div className="calculator">
      <div className="calculator-display">{displayValue}</div>
      <div className="calculator-keypad">
        <div className="input-keys">

          <div className="digit-keys">
            {/*<button className="number-keys" onClick={()=> this.inputDigit(0)}>0</button> This will Work*/}}
            <button className="number-keys">0</button>                
            <button className="number-keys1">1</button>
            <button className="number-keys">2</button>
            <button className="number-keys">3</button>
            <button className="number-keys">4</button>
            <button className="number-keys">5</button>
            <button className="number-keys">6</button>
            <button className="number-keys">7</button>
            <button className="number-keys">8</button>
            <button className="number-keys">9</button>
          </div>
        </div>          
      </div>
    </div>
  )
 }
}

【问题讨论】:

  • @jmargolisvt 伙计,我已经解释了为什么它不是重复的,而且错误消息也不同。您能否对这个问题投反对票?
  • 我没有对你投反对票。请注意,您得到的答案与我在副本中标记的答案相同。 :)

标签: javascript reactjs this


【解决方案1】:

那是因为你是在一个没有绑定的函数里面写的,

使用

var myFunction = function() {
    var targetNumber = Number(this.innerHTML);
    return this.inputDigit(targetNumber); 
  }.bind(this);

const myFunction = () => {
    var targetNumber = Number(this.innerHTML);
    return this.inputDigit(targetNumber); 
}

在这之后你还需要绑定 inputDigit 函数,因为它也使用 setState

//click handler function
inputDigit = (digit) => {
  const { displayValue } = this.state;
  this.setState({
    displayValue: displayValue+String(digit)
  })
}

由于您也想使用按钮文本,在这种情况下,您应该使用单独的变量代替 this 来调用 inputDigit 函数,如

class Calculator extends React.Component {

// display of calculator initially zero
state = {
  displayValue: '0'
}

//click handler function
inputDigit(digit){
  const { displayValue } = this.state;
  this.setState({
    displayValue: displayValue+String(digit)
  })
}

componentDidMount(){

  //Get all number keys and attach click handler function
  var numberKeys = document.getElementsByClassName("number-keys");
  var that = this;
  var myFunction = function() {
    var targetNumber = Number(this.innerHTML);
    console.log(targetNumber);
    return that.inputDigit(targetNumber); // This is not working
  };
  for (var i = 0; i < numberKeys.length; i++) {
    numberKeys[i].onclick = myFunction;
  }

}

render() {
  const { displayValue } = this.state;
  return (
    <div className="calculator">
      <div className="calculator-display">{displayValue}</div>
      <div className="calculator-keypad">
        <div className="input-keys">

          <div className="digit-keys">
            {/*<button className="number-keys" onClick={()=> this.inputDigit(0)}>0</button> This will Work*/}
            <button className="number-keys">0</button>                
            <button className="number-keys">1</button>
            <button className="number-keys">2</button>
            <button className="number-keys">3</button>
            <button className="number-keys">4</button>
            <button className="number-keys">5</button>
            <button className="number-keys">6</button>
            <button className="number-keys">7</button>
            <button className="number-keys">8</button>
            <button className="number-keys">9</button>
          </div>
        </div>          
      </div>
    </div>
  )
 }
} 

ReactDOM.render(<Calculator/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

【讨论】:

  • 我将 targetNumber 设为 NaN
  • Number(this.innerHTML) 返回什么
  • 它正在返回 NaN
  • 等一下,几分钟后将创建一个有效的 sn-p 并发布
  • 实际上需要添加数字才能显示为字符串,所以我删除Number,然后我得到undefined
【解决方案2】:

在构造函数中绑定

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

【讨论】:

  • OP 使用"plugins": ["transform-class-properties"] 不必这样做。绑定每个组件方法可能会变得混乱,这就是为什么他们在构造函数中使用state = 而不是this.state
  • state = 不在构造函数中,您不需要对每个方法都这样做。只是您需要执行回调或任何受上下文更改影响的函数。
猜你喜欢
  • 2017-03-19
  • 2017-07-16
  • 2016-05-26
  • 2020-10-25
  • 1970-01-01
  • 1970-01-01
  • 2016-05-03
  • 2012-12-24
  • 2021-07-10
相关资源
最近更新 更多