title: Multiple setState() calls in a React method: How to make it work "synchronously"
body: <p>So I had a problem in my React application, I ran into a specific case where I needed to have multiple <code>setState()</code> calls in one method, and then have code run <strong>AFTER</strong> the states were set. The code below is a Dialog box used to add an account on the website.</p>
  
  <pre><code>import React from 'react';
  import Dialog from 'material-ui/Dialog';
  import FlatButton from 'material-ui/FlatButton';
  import TextField from 'material-ui/TextField';
  
  /**
   * A modal dialog can only be closed by selecting one of the actions.
   */
  export default class NewAcctDia extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        open: false,
        userError: null,
        passError: null,
        passConfirmError: null,
      }
  
      this.handleOpen = this.handleOpen.bind(this);
      this.handleClose = this.handleClose.bind(this);
      this.handleSubmit = this.handleSubmit.bind(this);
    }
  
    handleOpen() {
      this.setState({open: true});
    }
  
    handleClose() {
      this.setState({open: false});
    }
  
    handleSubmit() {
      if(!this.refs.user.getValue())
        this.setState({userError: "This field is required"});
      else
        this.setState({userError: null});
  
      if(!this.refs.pass.getValue())
        this.setState({passError: "This field is required"});
      else
        this.setState({passError: null});
  
      if(this.refs.pass.getValue() == this.refs.passConfirm.getValue()) {
        this.setState({passError: null});
      } else {
        this.setState({passConfirmError: "Passwords do not match"});
      }
  
      if(!this.state.userError &amp;&amp; !this.state.passError &amp;&amp; !this.state.passConfirmError)
        alert('worked');
    }
  
    render() {
      const actions = [
        &lt;FlatButton
          label="Cancel"
          primary={true}
          onTouchTap={this.handleClose}
        /&gt;,
        &lt;FlatButton
          label="Submit"
          primary={true}
          disabled={false}
          onTouchTap={this.handleSubmit}
        /&gt;,
      ];
  
      return (
          &lt;Dialog
            title="Create an Account"
            actions={actions}
            modal={true}
            open={this.state.open}
            contentStyle={{width: 350}}
          &gt;
            &lt;TextField
              ref='user'
              floatingLabelText="Username"
              errorText={this.state.userError}
            /&gt;&lt;br /&gt;
            &lt;TextField
              ref='pass'
              floatingLabelText="Password"
              type="password"
              errorText={this.state.passError}
            /&gt;&lt;br /&gt;
            &lt;TextField
              ref='passConfirm'
              floatingLabelText="Confirm Password"
              type="password"
              errorText={this.state.passConfirmError}
            /&gt;&lt;br /&gt;
          &lt;/Dialog&gt;
      );
    }
  }
  </code></pre>
  
  <p>The problem is in the <code>handleSubmit()</code> method, I needed to check to see that the user had entered something into the username and password fields, and that the passwords and confirm password fields matched. If they didn't, I would add error text to the fields that needed alteration via state. I then tried to look at the state to see if there were any errors.</p>
  
  <p>Unfortunately, as I quickly figured out, the <code>setState()</code> function is asynchronous, meaning the state would not get changed before my final check. I googled and searched all over for a way to wait for state to change before executing code but came up empty. I've solved this problem now and figured I would put it up on Stack so others might benefit from the method I came up with. I would also like to know any pros and cons of what I am doing, or any suggestions that might work better.</p>
  
  <p>When I googled around I came across a method to send a callback to <code>setState()</code> as shown: <code>setState(data, callback)</code>. I did not think this would work for me at first, as I had multiple <code>setState()</code> calls. However, I realized I could convert the <code>handleSubmit()</code> method to a single <code>setState()</code> call with ternaries. Like so:</p>
  
  <pre><code>handleSubmit() {
      this.setState({
        userError: (
          this.refs.user.getValue() ? null : "This field is required"
        ),
        passError: (
          this.refs.pass.getValue() ? null : "This field is required"
        ),
        passConfirmError: (
          (this.refs.pass.getValue() == this.refs.passConfirm.getValue()) ? 
            null : "Passwords do not match"
        )
      }, () =&gt; {
        if(!this.state.userError &amp;&amp; !this.state.passError &amp;&amp; !this.state.passConfirmError)
          alert('worked');
      })
  }
  </code></pre>
  
  <p>The anonymous callback function will be executed after the state is changed, allowing my check to work.</p>
  
  <p>The only problems I foresee with this method are nested ternaries, as that may become extremely messy if they are required. Is there any adverse effects this might have on my program? Or better ways I could have solved this?</p>
  
  <p>I hope I've helped some people with my solution. :D</p>