shadcn.io is an independent project built on shadcn/ui
useEventCallback returns a function that keeps the same identity and still calls your latest function.
Do not call it while rendering. Before the effect stores your function, that call throws. Afterward, a click or a timer sees the newest state. When the subscription itself should stay put, see useEventListener. In React pass this down when a child should not rerender only because the parent rendered.
Installation
Anatomy

Usage
import { useEventCallback } from "@/hooks/use-event-callback";const onClick = useEventCallback(() => {
setCount(count + 1);
});FAQ
When should I use useEventCallback instead of useCallback?
useCallback returns a new function when a dependency changes. useEventCallback returns one function for the life of the component, built with an empty dependency list. Your latest function is stored on a ref after commit and called from that stable wrapper. Use it when a child, an effect, or a timer should keep the same function and still see new state.
How does this avoid a stale closure?
A stale closure reads state from the render that created the function. This hook writes your function onto a ref after each commit, and the stable wrapper calls whatever is on that ref. The function from the latest commit closes over that render. The wrapper does not close over your state. A call during render, before the ref updates, still runs the previous function.
Can I call the returned function during render?
Not on the first render. That call throws Cannot call an event handler while rendering. The ref starts as that throwing function, and an effect replaces it with yours after commit. On a later render the call does not throw. It runs the function from the previous commit, because the ref updates after render. Call it from a click, an effect, or a timer.
What if I pass undefined?
The hook still returns a function. The overload that accepts undefined types the result as a function or undefined, but the implementation always returns the wrapper from useCallback. If the stored function is undefined, calling the wrapper returns undefined instead of throwing. Pass undefined when the handler is sometimes absent. A defined function keeps its own return type.
Which effect stores the function on the server?
On the server the hook uses useEffect, which does not run during that render, so the ref still holds the throwing function afterward. On the client it uses useLayoutEffect, which stores your function after DOM updates and before the browser paints. A click happens after that, so it sees your function. Do not call the wrapper during render on either side.
Do I have to pass type arguments?
No. The argument list and the return type are inferred from the function you pass. One overload requires a function and returns a function of the same shape. The other also accepts undefined. You can write the type arguments when inference is not enough, but the usual call does not need them. The wrapper is cast so a defined function does not look like it returns undefined.
API Reference
Parameters
fn((...args: Args) => R) | undefined
The function to call; undefined makes the stable function return undefined.
- Type
((...args: Args) => R) | undefined
Returns
returns((...args: Args) => R) | undefined
A stable function with fn's arguments and result.
- Type
((...args: Args) => R) | undefined











