title: React hooks: accessing up-to-date state from within a callback
body: <p>EDIT (22 June 2020): as this question has some renewed interest, I realise there may be a few points of confusion. So I would like to highlight: the example in the question is intended as a toy example. It is not reflective of the problem. The problem which spurred this question, is in the use a third party library (over which there is limited control) that takes a callback as argument to a function. What is the correct way to provide that callback with the latest state. In react classes, this would be done through the use of <code>this</code>. In React hooks, due to the way state is encapsulated in the functions of <code>React.useState()</code>, if a callback <em>gets</em> the state through <code>React.useState()</code>, it will be stale (the value when the callback was setup). But if it <em>sets</em> the state, it will have access to the latest state through the passed argument. This means we can potentially get the latest state in such a callback with React hooks by <em>setting</em> the state to be the same as it was. This works, but is counter-intuitive.</p>
  <p>-- Original question continues below --</p>
  <p>I am using React hooks and trying to read state from within a callback. Every time the callback accesses it, it's back at its default value.</p>
  <p>With the following code. The console will keep printing <code>Count is: 0</code> no matter how many times I click.</p>
  <pre><code>function Card(title) {
    const [count, setCount] = React.useState(0)
    const [callbackSetup, setCallbackSetup] = React.useState(false)
    
    function setupConsoleCallback(callback) {
      console.log(&quot;Setting up callback&quot;)
      setInterval(callback, 3000)
    }
  
    function clickHandler() {
      setCount(count+1);
      if (!callbackSetup) {
        setupConsoleCallback(() =&gt; {console.log(`Count is: ${count}`)})
        setCallbackSetup(true)
      }
    }
    
    
    return (&lt;div&gt;
        Active count {count} &lt;br/&gt;
        &lt;button onClick={clickHandler}&gt;Increment&lt;/button&gt;
      &lt;/div&gt;);
    
  }
  
  const el = document.querySelector(&quot;#root&quot;);
  ReactDOM.render(&lt;Card title='Example Component' /&gt;, el);
  </code></pre>
  <p><em>You can find this code <a href="https://codepen.io/rodh/pen/zYORLvL" rel="noreferrer">here</a></em></p>
  <p>I've had no problem setting state within a callback, only in accessing the latest state.</p>
  <p>If I was to take a guess, I'd think that any change of state creates a new instance of the Card function. And that the callback is referring to the old one. Based on the documentation at <a href="https://reactjs.org/docs/hooks-reference.html#functional-updates" rel="noreferrer">https://reactjs.org/docs/hooks-reference.html#functional-updates</a>, I had an idea to take the approach of calling setState in the callback, and passing a function to setState, to see if I could access the current state from within setState. Replacing</p>
  <pre><code>setupConsoleCallback(() =&gt; {console.log(`Count is: ${count}`)})
  </code></pre>
  <p>with</p>
  <pre><code>setupConsoleCallback(() =&gt; {setCount(prevCount =&gt; {console.log(`Count is: ${prevCount}`); return prevCount})})
  </code></pre>
  <p><em>You can find this code <a href="https://codepen.io/rodh/pen/OJLQwOW" rel="noreferrer">here</a></em></p>
  <p>That approach hasn't worked either.
  EDIT: Actually that second approach <em>does</em> work. I just had a typo in my callback. This is the correct approach. I need to call setState to access the previous state. Even though I have no intention of setting the state.</p>
  <p>I feel like I've taken similar approaches with React classes, but. For code consistency, I need to stick with React Effects.</p>
  <p>How can I access the latest state information from within a callback?</p>