bind(this)
can fix this issue, and nowadays we can use another 2 ways to achieve this if you don't like using bind
.
1) As the traditional way, we can use bind(this)
in the constructor, so that when we use the function as JSX callback, the context of this
is the class itself.
class App1 extends React.Component {
constructor(props) {
super(props);
// If we comment out the following line,
// we will get run time error said `this` is undefined.
this.changeColor = this.changeColor.bind(this);
}
changeColor(e) {
e.currentTarget.style.backgroundColor = "#00FF00";
console.log(this.props);
}
render() {
return (
<div>
<button onClick={this.changeColor}> button</button>
</div>
);
}
}
2) If we define the function as an attribute/field of the class with arrow function, we don't need to use bind(this)
any more.
class App2 extends React.Component {
changeColor = e => {
e.currentTarget.style.backgroundColor = "#00FF00";
console.log(this.props);
};
render() {
return (
<div>
<button onClick={this.changeColor}> button 1</button>
</div>
);
}
}
3) If we use arrow function as JSX callback, we don't need to use bind(this)
either. And further more, we can pass in the parameters. Looks good, isn't it? but its drawback is the performance concern, for details please refer ReactJS doco.
class App3 extends React.Component {
changeColor(e, colorHex) {
e.currentTarget.style.backgroundColor = colorHex;
console.log(this.props);
}
render() {
return (
<div>
<button onClick={e => this.changeColor(e, "#ff0000")}> button 1</button>
</div>
);
}
}
And I have created a Codepen to demo these code snippets, hope it helps.