Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsWindows FixRecommendedWindows errors stealing your time? Find the fix fastScan stability, cleanup and performance issues.Fix Now×
Skip to content
World desk4 min

React 19 use() Rules: Where Conditional Calls Are Safe

React 19’s use() API is a narrow exception to Hook call-order rules. See when conditional calls are valid, how Promise reads suspend, and why ordinary Hooks still belong at the top level.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.”

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

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.

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.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.