shadcn-ahooks
External Hooks

useCallbackEvent

The API useCallbackEvent

useCallBackEvent

A hook that ensures callback functions always reference the latest version without causing component re-renders, similar to React's experimental useEffectEvent.

Features

  • ✅ Always calls the latest callback function
  • 🎯 Stable function reference (doesn't change between renders)
  • 🚀 Prevents unnecessary re-renders in child components
  • 🔄 Solves closure issues with callbacks

When to Use

  • Event handlers passed to memoized child components
  • Callbacks in useEffect that need access to latest state
  • Functions passed to third-party libraries or event listeners
  • Avoiding stale closure problems

Installation

Open in
pnpm dlx shadcn@latest add https://shadcn-ahooks.vercel.app/r/useCallbackEvent.json
npx shadcn@latest add https://shadcn-ahooks.vercel.app/r/useCallbackEvent.json
yarn shadcn@latest add https://shadcn-ahooks.vercel.app/r/useCallbackEvent.json
bun shadcn@latest add https://shadcn-ahooks.vercel.app/r/useCallbackEvent.json

Usage

Examples

Basic Usage - Solving Stale Closure

Preventing Re-renders with Memoized Children

With Event Listeners

With Third-Party Libraries

API

const stableCallback = useCallbackEvent<T>(callback: T): T

Params

PropertyDescriptionTypeRequired
callbackThe callback function to wrap(...args: any[]) => anyYes

Result

PropertyDescriptionType
stableCallbackA stable function reference that always calls the latest callback(...args: any[]) => any

Comparison with Other Approaches

vs useCallback

// useCallback: Need to include all dependencies
const callback = useCallback(() => {
  console.log(stateA, stateB, stateC);
}, [stateA, stateB, stateC]); // Re-creates when any dep changes

// useCallbackEvent: Always stable, always latest
const callback = useCallbackEvent(() => {
  console.log(stateA, stateB, stateC);
}); // Never re-creates

vs useRef

// useRef: Manual management, verbose
const callbackRef = useRef(callback);
useEffect(() => {
  callbackRef.current = callback;
}, [callback]);
const stableCallback = useCallback((...args) => {
  return callbackRef.current(...args);
}, []);

// useCallbackEvent: Simple and clean
const stableCallback = useCallbackEvent(callback);

How It Works

  1. Stores Latest Callback: Uses useImperativeHandle to store the current callback
  2. Stable Wrapper: Returns a memoized function (via useCallback with empty deps)
  3. Latest Execution: The wrapper always calls the stored latest callback
  4. No Re-creation: The returned function reference never changes

Notes

  • This is similar to React's experimental useEffectEvent hook (not yet stable)
  • The returned function reference is stable and won't cause re-renders
  • The callback always has access to the latest props, state, and context
  • Perfect for event handlers, callbacks in effects, and third-party library integrations
  • Throws an error if called when the callback reference is null (edge case protection)

TypeScript

function useCallbackEvent<T extends (...args: unknown[]) => unknown>(
  callback: T
): (...args: Parameters<T>) => ReturnType<T>;

The hook is fully typed and preserves the callback's parameter and return types.

On this page