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

  1. Only invoke the returned function inside event handlers, effects, timeouts, or other callbacks — never in the render body.
  2. If you genuinely need the value during render, use useMemo/useCallback or read state directly instead of useCallbackRef.
  3. In tests, wrap synchronous calls in act() and ensure effects flush before invoking.
  4. 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

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.