useEventCallbackLoading saved progress…

useEventCallback

There's a recurring tension in React: you want a callback with a stable identity (so it doesn't break React.memo children or re-trigger effects), but you also want it to see the latest props and state (not a value frozen when the callback was created). useCallback gives you one or the other — an empty dep array is stable but goes stale; listing deps stays fresh but changes identity. useEventCallback gives you both, and it's the pattern behind React's proposed useEvent.

Implement useEventCallback(fn). Return a function whose identity never changes across renders, but that always invokes the most recent fn — forwarding arguments, return value, and this.

Signature

function useEventCallback(fn) {
  // returns a stable function that always calls the latest fn
}

Examples

function Chat({ roomId }) {
  const onSend = useEventCallback((msg) => sendTo(roomId, msg));
  // onSend has ONE identity forever, but always uses the current roomId
  useEffect(() => socket.on('ready', onSend), [onSend]); // effect never re-runs
}
const [count, setCount] = useState(0);
const log = useEventCallback(() => console.log(count)); // always the latest count

Notes

  • Stable identity — return the same function every render (memoized with empty deps) so memoized children and effect deps see no change.
  • Latest fn via a ref — store the newest fn in a ref and update it each render; the stable wrapper reads the ref when called.
  • Forward everything — pass through arguments, the return value, and this (use apply).
  • Don't call during render — like useEvent, the ref updates in a layout effect, so calling the wrapper mid-render could read a stale fn. Use it in handlers and effects.
Loading editor…