In React, you have to be careful with this in the JSX callback. Class methods don’t bind this by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when you call this function.
1. Bind this in the constructor or when called
<! DOCTYPEhtml>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make 'this' work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState= > ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />.document.getElementById('root'));</script>
</body>
</html>
Copy the code
By binding this to the call, the event object and more parameters will be passed implicitly
<! DOCTYPEhtml>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make 'this' work in the callback
//this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
e.preventDefault();
this.setState(prevState= > ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick.bind(this)}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />.document.getElementById('root'));</script>
</body>
</html>
Copy the code
2. Property initializer syntax
<! DOCTYPEhtml>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make 'this' work in the callback
//this.handleClick = this.handleClick.bind(this);
}
/ / look here
handleClick = () = > {
this.setState(prevState= > ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />.document.getElementById('root'));</script>
</body>
</html>
Copy the code
3. Use arrow function in callback function ()
<! DOCTYPEhtml>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make 'this' work in the callback
//this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(prevState= > ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
/* Use the arrow function */ in the callback function
<button onClick={ (e) = > this.handleClick(e) }>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
ReactDOM.render(
<Toggle />.document.getElementById('root'));</script>
</body>
</html>
Copy the code
The problem with using this syntax is that a different callback is created each time a LoggingButton is rendered. In most cases, this is fine. However, if this callback function is passed as a property value to lower-order components, those components may undergo additional re-rendering. We generally recommend binding or using property initializer syntax in constructors to avoid such performance problems.