2

I want set state after click button. But i have this error :

TypeError: this is undefined

class Welcome extends React.Component{

    constructor(props){
        super(props);
        this.state = {
            name: 'David'
        };
    }

    btnClick(){
        this.setState({name: 'Sarah'});
    }

    render(){

        return(
            <div>
                <button onClick={this.btnClick}>Change Name</button>
                <h1>{this.state.name}</h1>
            </div>
        );

    }

}

What's the right way for changing the React states ?

Mohammad
  • 4,441
  • 3
  • 13
  • 15
  • you need to bind btnClick in the constructor. `this.btnClick = this.btnClick.bind(this);` – brub Dec 20 '17 at 18:26

3 Answers3

2

You will need to bind the handler to the instance of the class.

Either do it explicit in the constructor:

constructor(props){
  super(props);
  this.state = {
    name: 'David'
  };
  this.btnClick = this.btnClick.bind(this);
}

Running example of your code:

class Welcome extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      name: 'David'
    };
    this.btnClick = this.btnClick.bind(this);
  }

  btnClick(){
    this.setState({ name: 'Sarah' });
  }

  render() {

    return (
      <div>
        <button onClick={this.btnClick}>Change Name</button>
        <h1>{this.state.name}</h1>
      </div>
    );

  }

}

ReactDOM.render(<Welcome />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Or use an arrow function which use the this reference in a lexical manner:

  btnClick = () => {
    this.setState({ name: 'Sarah' });
  }

Running example of your code:

class Welcome extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      name: 'David'
    };
  }

  btnClick = () => {
    this.setState({ name: 'Sarah' });
  }

  render() {

    return (
      <div>
        <button onClick={this.btnClick}>Change Name</button>
        <h1>{this.state.name}</h1>
      </div>
    );

  }

}

ReactDOM.render(<Welcome />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Sagiv b.g
  • 30,379
  • 9
  • 68
  • 99
1

You need to bind the method in constructor like this

constructor(props){
        super(props);
        this.state = {
            name: 'David'
        };
        this.btnClick = this.btnClick.bind(this)
    }

Alternatively you can also use arrow function syntax

   btnClick = () => {
        this.setState({name: 'Sarah'});
    }
Prakash Sharma
  • 15,542
  • 6
  • 30
  • 37
1

Have a look at this, you need to bind the method in the constructor or you can use arrow functions.

https://reactjs.org/docs/handling-events.html

Ezz
  • 534
  • 2
  • 8
  • 17