Reputation: 107
It is giving an error Cannot read property 'handleCheck' of undefined when I click on next button. Can anyone please help?Thanks in advance
import React from "react";
import ReactDOM from "react-dom";
class App extends React.Component {
state = { check: false };
handleCheck = () => {
console.log("hello");
this.setState({ check: !this.state.check });
};
componentDidMount() {
setTimeout(() => {
this.handleCheck();
}, 10000);
}
timer() {
setTimeout(() => {
this.handleCheck();
}, 10000);
}
render() {
return (
<div>
<p>hello</p>
{this.state.check ? (
<button onClick={this.timer}>Next</button>
) : (
<div>button not showing </div>
)}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));
Upvotes: 3
Views: 9451
Reputation: 1213
hi as previous people said you need to bind (this) one of the way is to do it like this
class App extends React.Component {
constructor(props) {
super(props);
this.state = { check: false };
// This binding is necessary to make `this` work in the callback
this.handleCheck = this.handleCheck.bind(this);
}
this is happens because when you enter a function the class this can't be reach bind solve this in regular function when you go with arrow function this scope don't use there on this scope instead they inherit the one from the parent scope like this: instead of:
timer() {
setTimeout(() => {
this.handleCheck();
}, 10000);
}
do this:
timer = () => {
setTimeout(() => {
this.handleCheck();
}, 10000);
}
Upvotes: 1
Reputation: 2114
You can use the arrow function as other users said, or as alternative you can manually bind this to the function:
// in the button
<button onClick={this.timer.bind(this)}>Next</button>
// or in the constructor
constructor(props) {
super(props)
this.timer = this.timer.bind(this)
}
<button onClick={this.timer)}>Next</button>
Upvotes: 1
Reputation: 211
You need to bind this to the timer function.
<button onClick={this.timer.bind(this)}>Next</button>
Upvotes: 1
Reputation: 7672
make it an arrow function:
timer = () => {
setTimeout(() => {
this.handleCheck();
}, 1000);
}
so it's bound to the parent scope
Upvotes: 3
Reputation: 58593
It's a binding issue of timer
function :
timer = () => {
setTimeout(() => {
this.handleCheck();
}, 10000);
}
OR change onClick
:
onClick={this.timer.bind(this)}
Solution :
class App extends React.Component {
state = { check: false };
handleCheck = () => {
console.log("hello");
this.setState({ check: !this.state.check });
};
componentDidMount() {
setTimeout(() => {
this.handleCheck();
}, 10000);
}
timer = () => {
setTimeout(() => {
this.handleCheck();
}, 10000);
}
render() {
return (
<div>
<p>hello</p>
{this.state.check ? (
<button onClick={this.timer}>Next</button>
) : (
<div>button not showing </div>
)}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("react-root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<div id="react-root"></div>
Upvotes: 1
Reputation: 10662
The timer
should also be an arrow function to refer to the correct this
:
timer = () => {
setTimeout(() => {
this.handleCheck();
}, 10000);
}
the other way to fix this would be to bind this
to timer
.
And since the new state depends on the old state, the handleCheck
function should be like this:
handleCheck = () => {
console.log("hello");
this.setState(prevState => ({ check: !prevState.check }));
};
Upvotes: 3