React 19’s use() API is a narrow exception to the usual rule that Hooks must be called in the same order on every render. You may call use(resource) conditionally or in a loop; you may not do the same with useState, useEffect, useContext, or custom Hooks. The exception applies only to use, and it still must run while a function component or custom Hook is rendering.
Why can use() be conditional when other Hooks cannot?
Ordinary Hooks such as useState rely on a consistent call order between renders. React uses that order to match each Hook call with its state and other bookkeeping. If a conditional or loop changes the sequence, React can associate values with the wrong calls or report errors such as “Rendered fewer hooks than expected” or “Rendered more hooks than expected.”
As an Amazon Associate I earn from qualifying purchases.
use(resource) reads a resource—a Promise or a context value—rather than adding a stateful Hook slot in that ordered sequence. React therefore permits this specific API to appear in a condition or loop. The React team stated in its React 19 announcement, published December 5, 2024: “The use API can only be called in render, similar to hooks. Unlike hooks, use can be called conditionally.”
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →This does not make every function beginning with use safe to call conditionally. Keep ordinary Hooks and custom Hooks at the top level of a function component or custom Hook, before early returns.
#1 Best Overall
Which calls are allowed in conditions or loops?
| Call | Conditional or loop call? | What it reads or does |
|---|---|---|
use(resource) |
Allowed | Reads a Promise or context value; Promise reads may suspend. |
useState, useEffect, useMemo, useContext, and custom Hooks |
Not allowed | Must be called in a consistent top-level order on every render. |
The distinction is useful when a component only needs a context value on one render path. For example, after returning early when there are no children, the remaining path can read a theme context with use(ThemeContext):
function Panel({ children }) {
if (!children) {
return null;
}
const theme = use(ThemeContext);
return <section className={theme} />;
}
The corresponding conditional state call is still invalid. Move the ordinary Hook to the top level and let the condition affect its input or later behavior instead:
function Panel({ enabled }) {
const [count, setCount] = useState(0);
if (!enabled) {
return null;
}
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
Similarly, use(Context) can be useful when a context read occurs after an early return or only inside a branch. It behaves similarly to useContext(Context), but the normal useContext call must still follow the top-level rule. Use the exception where control flow calls for it; do not mechanically replace every useContext.
What happens when use() reads a Promise?
use(promise) returns the Promise’s resolved value. If the Promise is still pending, the component that reads it suspends. The nearest applicable <Suspense> boundary above that component displays its fallback until the Promise resolves. Boundary placement determines how much of the interface waits.
Rank #3
If the Promise rejects, the error propagates to the nearest Error Boundary. Use Suspense to handle the pending state and an Error Boundary to handle rejection; do not wrap use(promise) in try/catch. The React Hooks lint guidance explicitly allows conditional and loop calls to use, while retaining the rendering and no-try/catch restrictions.
Use a cached Promise in Client Components
React’s React 19 release guidance warns against creating an uncached Promise during a Client Component or Hook render. It reports: “A component was suspended by an uncached promise. Creating promises inside a Client Component or hook is not yet supported, except via a Suspense-compatible library or framework.” Pass a Promise supplied by a Suspense-compatible library or framework that caches Promises; do not create a fresh Promise during that render.
Rank #4
Server Components and Client Components handle Promises differently
A Server Component can use await on a Promise directly, or pass the Promise further down for a deeper Server Component to await. A Client Component cannot use await during render; it can receive a Promise and unwrap it with use. In either case, suspension occurs where the Promise is read, so the nearest applicable Suspense boundary controls which interface region shows a fallback.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Why does React say “Rendered fewer hooks than expected”?
This error commonly means a render took a different path through ordinary Hooks than an earlier render. For example, an early return placed before a useState call can cause one render to skip that call while another reaches it. Conditional ordinary Hooks and calls inside loops can create the same mismatch.
Best Value
Check every path through the component and move ordinary Hooks to the top level, before any early return. Then check the eslint-plugin-react-hooks Rules of Hooks guidance: it flags conditional ordinary Hooks and custom Hooks, but documents the specific conditional and loop exception for use. If the changing call is use(promise), check Promise caching and the placement of Suspense and Error Boundaries as well.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




