mamadgi aishwarya
mamadgi aishwarya

Reputation: 107

React setTimeout hooks onclick

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

Answers (6)

TalOrlanczyk
TalOrlanczyk

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

CevaComic
CevaComic

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

skapicic
skapicic

Reputation: 211

You need to bind this to the timer function.

<button onClick={this.timer.bind(this)}>Next</button>

Upvotes: 1

Red Baron
Red Baron

Reputation: 7672

make it an arrow function:

  timer = () => {
    setTimeout(() => {
      this.handleCheck();
    }, 1000);
  }

so it's bound to the parent scope

Upvotes: 3

Vivek Doshi
Vivek Doshi

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

Ramesh Reddy
Ramesh Reddy

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

Related Questions