marmelab/react-admin · error · Error
Cannot call an event handler while rendering.
Error message
Cannot call an event handler while rendering.
What it means
useDebouncedEvent wraps a callback so it can only be invoked after render, via a ref that is populated in a layout effect. The ref's initial value throws this error, which happens if the debounced handler is invoked during the render phase before React has committed and run the effect.
Source
Thrown at packages/ra-core/src/util/useDebouncedEvent.ts:24
// allow the hook to work in SSR
const useLayoutEffect =
typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
/**
* Hook somewhat equivalent to useEvent, but with a debounce
* Returns a debounced callback which will not change across re-renders unless the
* callback or delay changes
* @see https://reactjs.org/docs/hooks-faq.html#how-to-read-an-often-changing-value-from-usecallback
* @see https://github.com/facebook/react/issues/14099#issuecomment-440013892
*/
export const useDebouncedEvent = <Args extends unknown[], Return>(
callback: (...args: Args) => Return,
delay: number
) => {
// Create a ref that stores the debounced callback
const debouncedCallbackRef = useRef<(...args: Args) => Return | undefined>(
() => {
throw new Error('Cannot call an event handler while rendering.');
}
);
// Keep a stable ref to the callback (in case it's an inline function for instance)
const stableCallback = useEvent(callback);
// Whenever callback or delay changes, we need to update the debounced callback
useLayoutEffect(() => {
debouncedCallbackRef.current = debounce(stableCallback, delay);
}, [stableCallback, delay]);
// The function returned by useCallback will invoke the debounced callback
// Its dependencies array is empty, so it never changes across re-renders
return useCallback(
(...args: Args) => debouncedCallbackRef.current(...args),
[]
);
};View on GitHub (pinned to 051f511bb0)
Solutions
- Move the call into an event handler, useEffect/useLayoutEffect, or async callback instead of render.
- Trigger initial invocations inside useEffect(() => { debouncedFn(); }, []).
- If a value is needed during render, compute it directly instead of calling the debounced handler.
Example fix
// before
const debounced = useDebouncedEvent(fn, 300);
debounced(); // during render -> throws
// after
const debounced = useDebouncedEvent(fn, 300);
React.useEffect(() => { debounced(); }, []); Defensive patterns
Strategy: validation
Validate before calling
// Never call the debounced handler in render; invoke it in an effect:
React.useEffect(() => {
debounced(args);
}, [deps]); Try / catch
try {
debounced(args);
} catch (e) {
if (e instanceof Error && e.message.includes('while rendering')) {
// move invocation to an effect/handler
}
} Prevention
- Treat hook-returned handlers as event/effect-time only.
- Use useEffect for any initial or reactive invocation.
- Enable React strict-mode audits / eslint react-hooks rules to catch render-phase side effects.
When it happens
Trigger: Calling the debounced function directly during a component's render body or inside another component's render (e.g. debounceFn() at the top level of the component function) instead of inside an event handler, effect, or timeout.
Common situations: Developers invoking hooks-returned handlers immediately for 'initial fetch', calling them inside render-time computations, or in class-style lifecycle-like patterns that run during render.
Related errors
- Cannot call an event handler while rendering.
- useTranslatableContext must be used inside a TranslatableCon
- useCloseNotification must be used within a CloseNotification
- usePreference cannot be used outside of a Configurable compo
- usePreferencesEditor must be used within a PreferencesEditor
AI-assisted analysis of marmelab/react-admin@051f511bb0 (2026-08-30).
Data as JSON: /api/errors/e488ff0c05eff60d.
Report an issue: GitHub.