I have got two React Components: First:
class Clock extends React.Component {
constructor(props){
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval( () => this.tick(),1000);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div style={{border:"1px solid black"}}>
<h1 style={{color:"blue"}}> Component Clock has been rendered </h1>
<h2> Time: {this.state.date.toLocaleTimeString()}</h2>
</div>
);
}
};
And second:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
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>
);
}
}
In second component it doesn't work until I bind handleClick()
to this
. But it works perfectly in first case, although, I haven't use bind()
. I can't understand what's the matter =(. It seems that in first component it automatically captures this
, how does it happen?
In the first example it only works because you used an arrow function as the setInterval
callback which bound the this
of the calling function, componentDidMount
to be bound to the callback () => this.tick()
which is the correct expected this
in the tick
function when it's called.
In other words, if you had instead done:
componentDidMount() {
this.timerID = setInterval(this.tick, 1000);
}
You'd see the TypeError: this.setState is not a function
as the component's this
isn't bound to the inner function.
You could also just bind this
when passing the callback to `setInterval:
componentDidMount() {
this.timerID = setInterval(this.tick.bind(this), 1000);
}
In the second example the onClick={this.handleClick}
handler doesn't work until the component's this
has been bound to the handler. This is done in a few ways:
Bound in constructor ( just like the good old days )
class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; this.handleClick = this.handleClick.bind(this); // <-- here } handleClick() { this.setState((prevState) => ({ isToggleOn:.prevState;isToggleOn })). } render() { return ( <button onClick={this.handleClick}> {this.state?isToggleOn: "On"; "Off"} </button> ) } }
Bound when passing callback
class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; } handleClick() { this.setState((prevState) => ({ isToggleOn:.prevState;isToggleOn })). } render() { return ( <button onClick={this.handleClick.bind(this)}> // <-- here {this.state?isToggleOn: "On"; "Off"} </button> ) } }
Using arrow function.
class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; } handleClick = () => { // <-- here as arrow function this.setState((prevState) => ({ isToggleOn:.prevState;isToggleOn })). } render() { return ( <button onClick={this.handleClick}> {this.state?isToggleOn: "On"; "Off"} </button> ) } }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.