简体   繁体   中英

How do I disable a button based on multiple states in React?

I'm building a form with React and I wanted to disable a button when the form is not 'valid', ie when one of the states is blank. The button looks at a state called disable_button . Here's what I have so far:

var MyForm = React.createClass({
  getInitialState: function() {
    return {
      group_id: '',
      ls_type_id: '',
      disable_button: false
    };
  },
  handleGroupChange: function(e) {
    this.setState({group_id: e.target.value});
  },
  handleTypeChange: function(e) {
    this.setState({ls_type_id: e.target.value});
  },
  handleClick: function() {
    console.log('Button clicked');
  },
  componentDidUpdate: function() {
    this.isFormValid();
  },
  isFormValid: function(){
    if (this.state.group_id == '' || this.state.ls_type_id == '') {
      this.setState({disable_button: true});
    } else {
      this.setState({disable_button: false});
    }
  },
  render: function() {
    return (
      <div>
        <select className='form-control' value={this.state.group_id} onChange={this.handleGroupChange}>
          <option value=''>Select group...</option>
          <option value='10'>Some group</option>
        </select>
        <br /> 
        <select className='form-control' value={this.state.ls_type_id} onChange={this.handleTypeChange}>
          <option value=''>Select type...</option>
          <option value='11'>Some type</option>
        </select>
        <br />
        <button className="btn btn-primary" onClick={this.handleClick} disabled={this.state.disable_button}>Save</button>
      </div>
    );
  }
});

ReactDOM.render(<MyForm />, document.getElementById('content'));

Running this code results in an Uncaught RangeError: Maximum call stack size exceeded and I realize why: it's because after the component updates, it calls my componentDidUpdate , which then updates a state, which then updates the component, and the loop occurs. So I don't really know how can I make the button disable when one of those states is blank. I might add more form fields so I didn't want to hardcode it to only look at these two selects.

Try this instead:

isFormValid: function(){
  return this.state.group_id == '' || this.state.ls_type_id == '';
}

...

<button disabled={this.isFormValid()} ...>

componentDidUpdate has two props passed in to it, prevProps and prevState as documented . You could use this fact in componentUpdate to only call isFormValid if either the type_id or ls_type_id has changed.

However, the cascading setState calls are a little inefficient. It might make more sense to determine disable_button in your render function, since you don't appear to be consuming it anywhere else. So, delete isFormValid and all calls to it, and put this in the beginning of render:

render: function () {
  var disable_button = false;
  if (this.state.group_id == '' || this.state.ls_type_id == '') {
    disable_button = true;
  }
  return ( <div> ...content </div>
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM