Tuesday, February 19, 2019

javascript - How to bind onclick handlers to `this` properly on React



Explanation to why this is not a duplicate: My code is already working, I have included as a comment. The question is why the this context change when I include it to click handler function.
I'm attempting a calculator project in React. The goal is to attach onclick handlers to number buttons so the numbers are displayed on the calculator display area. If the handler is written directly to render method it is working, however, if I'm trying from the ComponentDidMount I get an error this.inputDigit is not a function. How do I bind this.inputDigit(digit) properly?




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 (

{displayValue}






{/* This will Work*/}}















)
}
}


Answer



Thats because you are writing it inside a function which is not bound,



Use



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



or



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


After this you need to bind the inputDigit function as well since it also uses setState




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



Since you want to use the button text as well, in that case you should use a separate variable in place of this to call the inputDigit function like





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 (

{displayValue}






{/* This will Work*/}















)

}
}

ReactDOM.render(, document.getElementById('app'))








No comments:

Post a Comment

plot explanation - Why did Peaches&#39; mom hang on the tree? - Movies &amp; TV

In the middle of the movie Ice Age: Continental Drift Peaches' mom asked Peaches to go to sleep. Then, she hung on the tree. This parti...