2

Probably doing something stupid, but if anybody can help. I think this is undefined or something. So im trying to use setState and getting the following error.

line 20 Uncaught TypeError: Cannot read property 'setState' of undefined

import React from 'react';

class TimeoutModal extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      timeLeft: 60,
      timeoutModal: true
    };
  }

  componentDidMount() {
    setInterval(() =>{
      this.setState({ timeLeft: this.state.timeLeft - 1 });
    }, 1000);
  }

  handleClick(e) {
    this.setState({timeoutModal: false});
  }

  render() {
    console.log(this.props.timeoutStatus);
    return (
      <div className="timeout-modal">
        <div className="timeout-modal__container">
          <p>Would you like to continue? {this.state.timeLeft}</p>
          <button onClick={this.handleClick} className="timeout-modal__container-button">Yes</button>
        </div>
      </div>
    );
  }
}

export default TimeoutModal;
Adam Dodds
  • 21
  • 1
  • 4

2 Answers2

3

You need to bind the handleClick event with current component instance. So change the onChange event handler as.

<button onClick={this.handleClick.bind(this)} className="timeout-modal__container-button">Yes</button>

From the doc:

You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.

Much cleaner when you bind them inside the contructor function and then use them.

constructor(props) {
  super(props);
  this.state = {
    timeLeft: 60,
    timeoutModal: true
  };
  this.handleClick = this.handleClick.bind(this)
}

Write the handler now.

<button onClick={this.handleClick} className="timeout-modal__container-button">Yes</button>
Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317
1
  handleClick = (e) => {
    this.setState({timeoutModal: false});
  }

You should use arrow functions to have this working properly inside your function

Dinosan0908
  • 1,082
  • 2
  • 8
  • 19
  • With this approach, u no more need *arrow* function when adding them to handler props. – Arup Rakshit Aug 22 '18 at 11:14
  • Yes, but the definition of function stays the same and avoids to add a new line in the constructor to bind this. You maybe would like to read that piece of article https://github.com/getify/You-Dont-Know-JS/blob/master/es6%20&%20beyond/ch2.md#arrow-functions it explains really well – Dinosan0908 Aug 22 '18 at 11:20
  • The syntax you wrote is not yet standard. Although everybody using it with babel, even me. I have no problem with this style. What I said, when you write this syntax, no need to write `onClick={() => this.handleClick}` anymore. We can use this style, or the `.bind()` approach. In both we need no more `() => ()` with event handlers. – Arup Rakshit Aug 22 '18 at 11:24
  • Yes we agree :) – Dinosan0908 Aug 22 '18 at 11:25