chakra-ui/chakra-ui · error · Error
Cannot call an event handler while rendering.
Error message
Cannot call an event handler while rendering.
What it means
useCallbackRef is a user-land implementation of React's experimental useEffectEvent. The callback is stored in a ref whose initial value is a thunk that throws, ensuring the returned stable function is never invoked during the initial render pass (before useInsertionEffect has populated the ref). This enforces the React rule that effect-event callbacks may only fire from effects, event handlers, or callbacks — never synchronously while rendering.
Source
Thrown at packages/react/src/hooks/use-callback-ref.ts:14
"use client"
import { useCallback, useInsertionEffect, useRef } from "react"
/**
* This hook is user-land implementation of the experimental `useEffectEvent` hook.
* React docs: https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event
*/
export function useCallbackRef<Args extends unknown[], Return>(
callback: ((...args: Args) => Return) | undefined,
deps: React.DependencyList = [],
) {
const callbackRef = useRef<typeof callback>(() => {
throw new Error("Cannot call an event handler while rendering.")
})
useInsertionEffect(() => {
callbackRef.current = callback
})
// eslint-disable-next-line react-hooks/exhaustive-deps
return useCallback((...args: Args) => callbackRef.current?.(...args), deps)
}
View on GitHub (pinned to 13692aee26)
Solutions
- Only invoke the returned function inside event handlers, effects, timeouts, or other callbacks — never in the render body.
- If you genuinely need the value during render, use useMemo/useCallback or read state directly instead of useCallbackRef.
- In tests, wrap synchronous calls in act() and ensure effects flush before invoking.
- Confirm you are not passing the callback into a child that calls it during its own render.
Example fix
// before
const onClick = useCallbackRef(handler)
return <div>{onClick('x')}</div> // throws on first render
// after
const onClick = useCallbackRef(handler)
return <div onClick={() => onClick('x')} /> Defensive patterns
Strategy: validation
Validate before calling
// No pre-call validation possible — the error fires when the returned // callback is invoked during render. The guard is structural: never call // the returned function in the render phase.
Type guard
n/a (the contract is about *when* you call the returned function, not the input type)
Try / catch
try {
cb(...args)
} catch (e) {
if (String(e) === 'Cannot call an event handler while rendering.') {
// move the call into an effect/handler instead of swallowing
}
throw e
} Prevention
- Treat useCallbackRef's return value as an effect-event: call it only from effects, handlers, or callbacks.
- Never invoke it in JSX, useMemo, useReducer initializer, or the component body.
- In tests, flush effects (act()) before invoking.
- On SSR, remember useInsertionEffect does not run server-side — do not invoke the callback during SSR.
When it happens
Trigger: Calling the stable function returned by useCallbackRef during the first render — for example invoking it inline in JSX, inside useMemo, or directly in the component body before mount completes. Also triggered by tests or SSR that synchronously invoke the returned callback.
Common situations: Misusing the hook as a regular memoized callback that you can call during render; SSR/SSG where useInsertionEffect has not yet run; unit tests that synchronously call the returned function on a freshly mounted component.
Related errors
AI-assisted analysis of chakra-ui/chakra-ui@13692aee26 (2026-08-12).
Data as JSON: /api/errors/314e7f10fd53e71d.
Report an issue: GitHub.