Rooks
HooksUtilities & Refs

useFreshCallback

Returns a stable function that delegates to the latest callback after effects run.

About

useFreshCallback avoids stale closures without changing function identity on every render. It is useful for subscriptions and timers that should stay installed while their callback reads current props or state.

Example

import { useEffect, useState } from "react";
import { useFreshCallback } from "rooks";

export default function WindowWidthLogger() {
  const [label, setLabel] = useState("Window");
  const reportWidth = useFreshCallback(() => {
    console.log(`${label}: ${window.innerWidth}px`);
  });

  useEffect(() => {
    window.addEventListener("resize", reportWidth);
    return () => window.removeEventListener("resize", reportWidth);
  }, [reportWidth]);

  return (
    <label>
      Log label{" "}
      <input
        value={label}
        onChange={(event) => setLabel(event.currentTarget.value)}
      />
    </label>
  );
}

Parameters

  • callback: (...args: Args) => R — required function to keep fresh.

Return value

Returns (...args: Args) => R. Its identity stays stable, it forwards arguments and return values, and it calls the callback stored by the latest completed passive effect.

Behavior and lifecycle

The internal ref initially contains the first callback and is updated after every render in a passive effect. A call before that effect finishes can therefore reach the callback from the previous committed render. Errors are not intercepted; they propagate to the caller.

Compatibility and accessibility

The hook itself is platform-independent and SSR-safe. Browser access in the callback occurs only when the returned function is invoked. Accessibility depends on the event or control using it.

  • useFreshRef exposes the current value through .current.
  • useFreshTick calls the latest void callback but does not preserve wrapper identity.

On this page