Bala
Bala

Reputation: 11234

How to handle onChange event that sets the state in React?

I am learning React and in the below code I get ...cannot update during an existing state transition.... While looking to fix it, I read in SO that setState should not be used within render() as it calls render() repeatedly resulting in infinite loop. But I dont know how to fix it.

import React from 'react';
import ReactDOM from 'react-dom';

export default class CheckBox extends React.Component{
    constructor() {
        super();
        this.state = {isChecked: false};
    }
    handleChecked () {
        this.setState({isChecked: !this.state.isChecked});
    }
    render(){
        var txt;
        if (this.state.isChecked) {
            txt = 'checked'
        } else {
            txt = 'unchecked'
        }
        return(
          <div>
            <input type="checkbox" onChange={this.handleChecked()}/>
            <p>This box is {txt}</p>
          </div>
        );
    }
}

ReactDOM.render(<CheckBox/>, document.getElementById('hello'));

Upvotes: 2

Views: 10240

Answers (1)

Oleksandr T.
Oleksandr T.

Reputation: 77482

You should pass to onChange reference to function but not call it., in your example you are calling handleChecked(because there is () after function) and result pass to onChange however result in this case will be undefined so onChange looks like onChange={ undefined }. Also, you can't set state during the initial render, but you are trying to do it with this.handleChecked() which contains this.setState.

export default class CheckBox extends React.Component{
  constructor() {
    super();
    this.state = {isChecked: false};

    // set this (with .bind), 
    // because you need get methods from CheckBox, like .setState
    this.handleChecked = this.handleChecked.bind(this); 
  }

  handleChecked () {
    this.setState({isChecked: !this.state.isChecked});
  }

  render(){
    var txt;
    if (this.state.isChecked) {
      txt = 'checked'
    } else {
      txt = 'unchecked'
    }

    // remove () after handleChecked because you need pass 
    // reference to function
    // also add return statement before <div>
    return <div>
       <input type="checkbox" onChange={ this.handleChecked }/>
       <p>This box is {txt}</p>
    </div>
  }
}

Example

Upvotes: 7

Related Questions