title: When accessing a state variable from a useCallback, value is not updated
body: <p>At a certain place of my code I'm accessing a state variable of my component from a call back ( <code>UserCallback</code> ) and I find the state variable has not updated from the initial value and call back is referring to the initial value. As I read in the documentation when variable is passed as one of array items then it should update the function when it is updated. Following is a sample code.</p>
  <pre><code>
  const Child = forwardRef((props, ref) =&gt; {
    const [count, setCount] = useState(0);
    const node = useRef(null);
  
    useImperativeHandle(ref, () =&gt; ({
      increment() {
        setCount(count + 1);
      }
    }));
  
    const clickListener = useCallback(
      e =&gt; {
        if (!node.current.contains(e.target)) {
          alert(count);
        }
      },
      [count]
    );
  
    useEffect(() =&gt; {
      // Attach the listeners on component mount.
      document.addEventListener(&quot;click&quot;, clickListener);
      // Detach the listeners on component unmount.
      return () =&gt; {
        document.removeEventListener(&quot;click&quot;, clickListener);
      };
    }, []);
  
    return (
      &lt;div
        ref={node}
        style={{ width: &quot;500px&quot;, height: &quot;100px&quot;, backgroundColor: &quot;yellow&quot; }}
      &gt;
        &lt;h1&gt;Hi {count}&lt;/h1&gt;
      &lt;/div&gt;
    );
  });
  
  const Parent = () =&gt; {
    const childRef = useRef();
  
    return (
      &lt;div&gt;
        &lt;Child ref={childRef} /&gt;
        &lt;button onClick={() =&gt; childRef.current.increment()}&gt;Click&lt;/button&gt;
      &lt;/div&gt;
    );
  };
  
  export default function App() {
    return (
      &lt;div className=&quot;App&quot;&gt;
        &lt;Parent /&gt;
      &lt;/div&gt;
    );
  }
  
  
  </code></pre>
  <p>What I'm originally building is a custom confirmation modal. I have a state variable which set either <strong>display:block</strong> or <strong>display:none</strong> to the root element. Then if there is a click outside the component I need to close the modal by setting state variable to <strong>false</strong>. Following is the original function.</p>
  <pre><code>  const clickListener = useCallback(
      (e: MouseEvent) =&gt; {
        console.log('isVisible - ', isVisible, ' count - ', count, ' !node.current.contains(e.target) - ', !node.current.contains(e.target))
        if (isVisible &amp;&amp; !node.current.contains(e.target)) {
          setIsVisible(false)
        }
      },
      [node.current, isVisible],
    )
  </code></pre>
  <p>It doesn't get closed because <strong>isVisible</strong> is always <strong>false</strong> which is the initial value.</p>
  <p>What am I doing wrong here?</p>
  <p>For further clarifications following is the full component.</p>
  <pre><code>const ConfirmActionModal = (props, ref) =&gt; {
  
    const [isVisible, setIsVisible] = useState(false)
    const [count, setCount] = useState(0)
  
    const showModal = () =&gt; {
      setIsVisible(true)
      setCount(1)
    }
  
    useImperativeHandle(ref, () =&gt; {
      return {
        showModal: showModal
      }
    });
  
    const node = useRef(null)
    const stateRef = useRef(isVisible);
  
    const escapeListener = useCallback((e: KeyboardEvent) =&gt; {
      if (e.key === 'Escape') {
        setIsVisible(false)
      }
    }, [])
  
    useEffect(() =&gt; {
      stateRef.current = isVisible;
    }, [isVisible]);
  
    useEffect(() =&gt; {
      const clickListener = e =&gt; {
        if (stateRef.current &amp;&amp; !node.current.contains(e.target)) {
          setIsVisible(false)
        }
      };
  
      // Attach the listeners on component mount.
      document.addEventListener('click', clickListener)
      document.addEventListener('keyup', escapeListener)
      // Detach the listeners on component unmount.
      return () =&gt; {
        document.removeEventListener('click', clickListener)
        document.removeEventListener('keyup', escapeListener)
      }
    }, [])
  
    return (
      &lt;div ref={node}&gt;
        &lt;ConfirmPanel style={{ display : isVisible ? 'block': 'none'}}&gt;
          &lt;ConfirmMessage&gt;
            Complete - {isVisible.toString()} - {count}
          &lt;/ConfirmMessage&gt;
          &lt;PrimaryButton
            type=&quot;submit&quot;
            style={{
              backgroundColor: &quot;#00aa10&quot;,
              color: &quot;white&quot;,
              marginRight: &quot;10px&quot;,
              margin: &quot;auto&quot;
            }}
            onClick={() =&gt; {console.log(isVisible); setCount(2)}}
          &gt;Confirm&lt;/PrimaryButton&gt;
        &lt;/ConfirmPanel&gt;
      &lt;/div&gt;
  
    )
  
  }
  
  export default forwardRef(ConfirmActionModal)
  </code></pre>