Skip to main content

useLatest

Returns a stable ref that always holds the latest value, so long-lived closures can read fresh props, state or callbacks without stale captures.

When to use it​

  • Calling the latest callback from a timer, event listener or async handler without re-subscribing.
  • Keeping effects with stable dependencies while still reading current values.

Demo​

Click the button, then open the Console tab: the interval is created once but always logs the latest count.

Loading demo…

Signature​

function useLatest<T>(value: T): { readonly current: T };

Returns: a ref whose current is the latest value. It is synchronized after each commit, so read it inside callbacks or effects, not during render.

Example​

const onTickRef = useLatest(onTick);

useEffect(() => {
const id = setInterval(() => onTickRef.current(), 1000);
return () => clearInterval(id);
}, [onTickRef]);

Source​

src/hooks/use-latest.ts
import { useEffect, useRef } from "react";

/**
* Returns a ref that always holds the latest value passed to the hook.
*
* Useful for reading up-to-date props, state or callbacks from long-lived
* closures (timers, event listeners, async callbacks, effects with empty
* dependency arrays) without re-subscribing or capturing stale values.
*
* The ref is synchronized in an effect, so it is updated after each commit
* rather than during render. Read `ref.current` inside callbacks or effects,
* not while rendering.
*
* @param value - The value to keep in the ref.
* @returns A stable ref object whose `current` is the latest value.
*
* @example
* ```ts
* const onTickRef = useLatest(onTick);
*
* useEffect(() => {
* const id = setInterval(() => onTickRef.current(), 1000);
* return () => clearInterval(id);
* }, [onTickRef]);
* ```
*/
export const useLatest = <T>(value: T): { readonly current: T } => {
const ref = useRef(value);

useEffect(() => {
ref.current = value;
});

return ref;
};