satya164 / use-latest-callback

React hook which returns the latest callback without changing the reference.
https://npmjs.com/package/use-latest-callback
38 stars 7 forks source link

callback isn't latest #11

Open thomasttvo opened 2 months ago

thomasttvo commented 2 months ago

The best place to reproduce this is in jest, but it may very well happen in real life if the callback is called after awaiting some async operation. The main problem is useIsomorphicLayoutEffect delays setting the new callback, so if there's anything that runs before the effect kicks in, it gets the old callback instead.

- re-render
- new callback is generated, but not set
- async operation calls the wrapper callback
- useIsomorphicLayoutEffect sets new callback
- result: the callback that was called was old

I think the fix here is to just get rid of it and let ref.current = callback runs immediately upon re-render

ashwin1014 commented 2 months ago
function useLatestCallback<T extends (...args: A) => R, A extends unknown[], R>(callback: T): T {
  const ref = useRef<T>(callback);

  useIsomorphicLayoutEffect(() => {
    ref.current = callback;
  });

  const latestCallback = useCallback((...args: A) => {
    return ref.current(...args);
  }, []);

  return latestCallback as T;
}

export default useLatestCallback;

i think this does the trick