React throws this error when useDeferredValue is called inside a conditional statement, loop, or nested function. All hooks must be called in the same order on every render to maintain state consistency.
This error occurs when you violate React's Rules of Hooks by calling useDeferredValue conditionally or inside loops, nested functions, or after early returns. React hooks rely on a stable call order to correctly associate hook state with component instances across renders. The useDeferredValue hook, introduced in React 18, must follow the same rules as all other hooks: it must be called at the top level of your component function, before any conditional returns or branching logic. When hooks are called conditionally, React cannot guarantee they'll execute in the same order on every render, breaking the internal state management system. This restriction applies to all React hooks (useState, useEffect, useCallback, useDeferredValue, etc.) and is enforced by React's hook dispatcher, which tracks hook calls by their position in the call sequence rather than by name or identifier.
Move the useDeferredValue call to the top of your component function, before any conditional logic or early returns:
Before (incorrect):
function SearchResults({ query, showDeferred }) {
// ❌ Conditional hook call
if (showDeferred) {
const deferredQuery = useDeferredValue(query);
return <Results query={deferredQuery} />;
}
return <Results query={query} />;
}After (correct):
function SearchResults({ query, showDeferred }) {
// ✅ Hook at top level, always called
const deferredQuery = useDeferredValue(query);
const displayQuery = showDeferred ? deferredQuery : query;
return <Results query={displayQuery} />;
}The key is to always call the hook, then use conditional logic to determine which value to use in your JSX.
If you need different hook behavior based on conditions, split into separate components where each calls hooks unconditionally:
Before (incorrect):
function DataDisplay({ mode, value }) {
if (mode === 'deferred') {
const deferredValue = useDeferredValue(value); // ❌ Conditional
return <div>{deferredValue}</div>;
}
return <div>{value}</div>;
}After (correct):
function DeferredDisplay({ value }) {
const deferredValue = useDeferredValue(value); // ✅ Top level
return <div>{deferredValue}</div>;
}
function ImmediateDisplay({ value }) {
return <div>{value}</div>;
}
function DataDisplay({ mode, value }) {
// Conditional rendering, not conditional hooks
return mode === 'deferred'
? <DeferredDisplay value={value} />
: <ImmediateDisplay value={value} />;
}Never call useDeferredValue inside map, forEach, or callback functions. Instead, call it once at the top level:
Before (incorrect):
function ListWithDeferredItems({ items }) {
return (
<ul>
{items.map(item => {
const deferred = useDeferredValue(item.value); // ❌ Inside loop
return <li key={item.id}>{deferred}</li>;
})}
</ul>
);
}After (correct):
function DeferredItem({ value }) {
const deferred = useDeferredValue(value); // ✅ Top level in component
return <li>{deferred}</li>;
}
function ListWithDeferredItems({ items }) {
return (
<ul>
{items.map(item => (
<DeferredItem key={item.id} value={item.value} />
))}
</ul>
);
}All hook calls must happen before any conditional return statements:
Before (incorrect):
function Search({ query, enabled }) {
if (!enabled) return null; // ❌ Early return
const deferredQuery = useDeferredValue(query); // Hook after return
return <Results query={deferredQuery} />;
}After (correct):
function Search({ query, enabled }) {
const deferredQuery = useDeferredValue(query); // ✅ Before return
if (!enabled) return null;
return <Results query={deferredQuery} />;
}Install and configure eslint-plugin-react-hooks to catch Rules of Hooks violations during development:
npm install --save-dev eslint-plugin-react-hooksAdd to your ESLint config (.eslintrc.json):
{
"plugins": ["react-hooks"],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
}This will show errors in your IDE and during linting when hooks are called conditionally.
Why React enforces hook call order:
React doesn't use hook names or variables to track state - it uses the order hooks are called. Each hook call gets assigned an index (0, 1, 2, etc.) during the first render. On subsequent renders, React matches hooks to their previous state by index. If you call hooks conditionally, the order changes, causing React to assign state to the wrong hooks.
Alternative patterns for conditional deferred values:
If you truly need to conditionally apply deferred behavior, use this pattern:
function ConditionalDeferred({ value, shouldDefer }) {
const deferredValue = useDeferredValue(value);
// Always call hook, decide which value to use
const finalValue = shouldDefer ? deferredValue : value;
return <Display value={finalValue} />;
}useDeferredValue vs useTransition:
Both hooks help manage concurrent rendering, but useDeferredValue is better when you need to defer a value you receive from props or state, while useTransition is better when you control the state update itself. Neither can be called conditionally.
TypeScript and hook violations:
TypeScript cannot catch Rules of Hooks violations at compile time because they're runtime constraints. Always use the ESLint plugin for static analysis.
Performance implications:
Calling useDeferredValue unconditionally doesn't hurt performance - React will only create a deferred version when needed. The overhead of always calling the hook is negligible compared to the alternative of violating hook rules.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite