Rooks
HooksUtilities & Refs

useFreshRef

Keeps the latest committed value in a stable mutable ref.

About

useFreshRef gives long-lived callbacks access to changing data without reinstalling the resource that owns those callbacks.

Example

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

export default function LatestValueTimer() {
  const [value, setValue] = useState(0);
  const latestValue = useFreshRef(value);

  useEffect(() => {
    const timer = window.setInterval(() => {
      console.log(`Latest value: ${latestValue.current}`);
    }, 1_000);
    return () => window.clearInterval(timer);
  }, [latestValue]);

  return (
    <button type="button" onClick={() => setValue((current) => current + 1)}>
      Value: {value}
    </button>
  );
}

Parameters

  • value: T — required value copied into the ref after each render.
  • preferLayoutEffect?: boolean — uses an isomorphic layout effect when true; otherwise a passive effect. Defaults to false and should remain constant across renders.

Return value

Returns a stable MutableRefObject<T>. Its initial .current is the first value.

Behavior and lifecycle

With the default passive effect, .current changes after the commit is painted; immediately before that effect, it can still hold the prior committed value. The layout-effect mode updates before browser paint and falls back to a passive effect on the server. The hook never schedules a render when .current changes.

Compatibility and accessibility

The ref logic is SSR-safe and has no browser dependency. Because ref changes do not render UI, do not use .current alone for user-visible state or accessible status messages.

  • useFreshCallback wraps a callback with stable identity and preserves its return value.
  • useFreshTick offers a void-callback convenience wrapper.

On this page