title: useEffect() cleanup functions not updating state in the expected order
body: <p>I'm looking to have child components update a state value through the <code>useContext</code> hook when they are unmounted from the DOM, but am unable to make sense of the order in which their clean up functions (the functions returned from a <code>useEffect</code> hook) are called.</p>
  <p>What I'm trying to achieve in the example code is to have the switches all individually able to modify the count of switches in an &quot;on&quot; state so that it's accurate, but also when they are removed from the DOM by the &quot;Remove all switches&quot; button they do the same. It seems like what is happening is that those updates when they are removed from the DOM are not happening in the order I'd expect, and the final state of that counter is not accurate.</p>
  <p>If you add several of the switches, turn several of them &quot;on&quot;, and then remove all of them, you'll see that the counter in the parent component is not set correctly. I've added a <code>console.log</code> call in the returned function from the <code>useEffect</code> hook, what's especially confusing here to me is that it looks like the counter is being set correctly, but somehow not in the correct order?</p>
  <p>(<a href="https://stackblitz.com/edit/react-qhgph4?file=src/App.js" rel="nofollow noreferrer">Here</a> is the example code running on StackBlitz.)</p>
  <pre><code>import React, { useState, createContext, useContext, useEffect } from 'react';
  import './style.css';
  
  const SwitchContext = createContext();
  
  const ChildComponent = () =&gt; {
    const [switchOn, setSwitchOn] = useState(false);
    const { numberOfSwitchesOn, setNumberOfSwitchesOn } =
      useContext(SwitchContext);
  
    useEffect(() =&gt; {
      return () =&gt; {
        if (switchOn) {
          console.log(
            `Setting number of switches on to: ${numberOfSwitchesOn - 1}`
          );
          setNumberOfSwitchesOn(numberOfSwitchesOn - 1);
        }
      };
    }, [switchOn]);
  
    const toggleSwitch = () =&gt; {
      if (switchOn) {
        // We are turning off this switch...
        setNumberOfSwitchesOn(numberOfSwitchesOn - 1);
      } else {
        // We are turning it on...
        setNumberOfSwitchesOn(numberOfSwitchesOn + 1);
      }
  
      setSwitchOn(!switchOn);
    };
  
    return (
      &lt;button onClick={() =&gt; toggleSwitch()}&gt;{switchOn ? 'on' : 'off'}&lt;/button&gt;
    );
  };
  
  export default function App() {
    const [numberOfSwitches, setNumberOfSwitches] = useState(1);
    const [numberOfSwitchesOn, setNumberOfSwitchesOn] = useState(0);
  
    let switches = [];
    for (let i = 0; i &lt; numberOfSwitches; i++) {
      switches.push(&lt;ChildComponent key={`switch-${i}`} /&gt;);
    }
  
    return (
      &lt;SwitchContext.Provider
        value={{
          numberOfSwitchesOn,
          setNumberOfSwitchesOn,
        }}
      &gt;
        &lt;div&gt;
          &lt;button onClick={() =&gt; setNumberOfSwitches(numberOfSwitches + 1)}&gt;
            Add switch
          &lt;/button&gt;
          &lt;button onClick={() =&gt; setNumberOfSwitches(0)}&gt;
            Remove all switches
          &lt;/button&gt;
          &lt;p&gt;Number of switches on: {numberOfSwitchesOn}&lt;/p&gt;
          {switches}
        &lt;/div&gt;
      &lt;/SwitchContext.Provider&gt;
    );
  }
  </code></pre>