title: How to make sure a React state using useState() hook has been updated?
body: <p>I had a class component named <code>&lt;BasicForm&gt;</code> that I used to build forms with. It handles validation and all the form <code>state</code>. It provides all the necessary functions (<code>onChange</code>, <code>onSubmit</code>, etc) to the inputs (rendered as <code>children</code> of <code>BasicForm</code>) via React context.</p>
  
  <p>It works just as intended. The problem is that now that I'm converting it to use React Hooks, I'm having doubts when trying to replicate the following behavior that I did when it was a class:</p>
  
  <pre><code>class BasicForm extends React.Component {
  
    ...other code...
  
    touchAllInputsValidateAndSubmit() {
  
      // CREATE DEEP COPY OF THE STATE'S INPUTS OBJECT
      let inputs = {};
      for (let inputName in this.state.inputs) {
        inputs = Object.assign(inputs, {[inputName]:{...this.state.inputs[inputName]}});
      }
  
      // TOUCH ALL INPUTS
      for (let inputName in inputs) {
        inputs[inputName].touched = true;
      }
  
      // UPDATE STATE AND CALL VALIDATION
      this.setState({
        inputs
      }, () =&gt; this.validateAllFields());  // &lt;---- SECOND CALLBACK ARGUMENT
    }
  
    ... more code ...
  
  }
  
  </code></pre>
  
  <p>When the user clicks the submit button, <code>BasicForm</code> should 'touch' all inputs and only then call <code>validateAllFields()</code>, because validation errors will only show if an input has been touched. So if the user hasn't touched any, <code>BasicForm</code> needs to make sure to 'touch' every input before calling the <code>validateAllFields()</code> function.</p>
  
  <p>And when I was using classes, the way I did this, was by using the second callback argument on the <code>setState()</code> function as you can see from the code above. And that made sure that <code>validateAllField()</code> only got called after the state update (the one that touches all fields).</p>
  
  <p>But when I try to use that second callback parameter with state hooks <code>useState()</code>, I get this error:</p>
  
  <pre><code>const [inputs, setInputs] = useState({});
  
  ... some other code ...
  
  setInputs(auxInputs, () =&gt; console.log('Inputs updated!'));
  </code></pre>
  
  <blockquote>
    <p>Warning: State updates from the useState() and useReducer() Hooks
    don't support the second callback argument. To execute a side effect
    after rendering, declare it in the component body with useEffect().</p>
  </blockquote>
  
  <p>So, according to the error message above, I'm trying to do this with the <code>useEffect()</code> hook. But this makes me a little bit confused, because as far as I know, <code>useEffect()</code> is not based on state updates, but in render execution. It executes after every render. And I know React can queue some state updates before re-rendering, so I feel like I don't have full control of exactly when my <code>useEffect()</code> hook will be executed as I did have when I was using classes and the <code>setState()</code> second callback argument.</p>
  
  <p>What I got so far is (it seems to be working):</p>
  
  <pre><code>function BasicForm(props) {
  
    const [inputs, setInputs] = useState({});
    const [submitted, setSubmitted] = useState(false);
  
    ... other code ...
  
    function touchAllInputsValidateAndSubmit() {
      const shouldSubmit = true;
  
      // CREATE DEEP COPY OF THE STATE'S INPUTS OBJECT
      let auxInputs = {};
      for (let inputName in inputs) {
        auxInputs = Object.assign(auxInputs, {[inputName]:{...inputs[inputName]}});
      }
  
      // TOUCH ALL INPUTS
      for (let inputName in auxInputs) {
        auxInputs[inputName].touched = true;
      }
  
      // UPDATE STATE
      setInputs(auxInputs);
      setSubmitted(true);
    }
  
    // EFFECT HOOK TO CALL VALIDATE ALL WHEN SUBMITTED = 'TRUE'
    useEffect(() =&gt; {
      if (submitted) {
        validateAllFields();
      }
      setSubmitted(false);
    });
  
    ... some more code ...
  
  }
  
  </code></pre>
  
  <p>I'm using the <code>useEffect()</code> hook to call the <code>validateAllFields()</code> function. And since <code>useEffect()</code> is executed on <strong>every render</strong> I needed a way to know when to call <code>validateAllFields()</code> since I don't want it on every render. Thus, I created the <code>submitted</code> state variable so I can know when I need that effect.</p>
  
  <p>Is this a good solution? What other possible solutions you might think of? It just feels really weird.</p>
  
  <p>Imagine that <code>validateAllFields()</code> is a function that CANNOT be called twice under no circunstances. How do I know that on the next render my <code>submitted</code> state will be already 'false' 100% sure?</p>
  
  <p>Can I rely on React performing every queued state update before the next render? Is this guaranteed?</p>