How to make sure a React state using useState() hook has been updated? : <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>
