iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

use() (React 19)

The React 19 use() hook: read promises and contexts inside components, with concurrent rendering doing the wait.

React — use() hook

EXAMPLE
// ===== use(promise) =====
// React 19+ lets you 'use' a promise inside a component.
// React suspends until it resolves, integrating with <Suspense>.

import { Suspense, use } from 'react';

function User({ userPromise }) {
  const user = use(userPromise);   // suspends until resolved
  return <p>{user.name}</p>;
}

function App() {
  const promise = fetch('/api/me').then(r => r.json());
  return (
    <Suspense fallback={<p>Loading...</p>}>
      <User userPromise={promise} />
    </Suspense>
  );
}

// ===== use(context) =====
// Replacement for useContext that works in conditionals + loops.
import { createContext, use } from 'react';

const ThemeContext = createContext('light');

function Card({ flag }) {
  if (!flag) return null;
  const theme = use(ThemeContext);    // OK inside if, unlike useContext
  return <div className={theme}>...</div>;
}

// ===== Difference from useContext =====
// useContext MUST be called at the top level.
// use() CAN be called inside conditionals + loops, returning context or promise.

// ===== Stable promises pattern =====
// Inline promises create a new one each render -> infinite suspense loop.
// Cache them with use() helpers from libraries (React Server Components / framework support):

// Wrong:
function Bad() {
  return <User userPromise={fetch(...).then(r => r.json())} />;  // new every render
}

// Right (cache):
let userPromise;
function getUserOnce() {
  userPromise ??= fetch('/api/me').then(r => r.json());
  return userPromise;
}
function Good() {
  return <User userPromise={getUserOnce()} />;
}

// Or rely on a framework / cache wrapper (React Cache, TanStack Query, etc).

// ===== Server Components flow (Next.js / Remix) =====
// In RSC, the server creates the promise and passes it to a Client Component.
// The client uses use() to read it as data streams in.

// ===== Patterns to internalise =====
// - use() with <Suspense> for declarative loading states
// - use() with context inside conditional / loops
// - Stable promise references (framework-provided cache)
// - Pair use() with error boundaries for failure UX

// ===== Pitfalls =====
// - New promise every render -> infinite re-suspends
// - use() without an ancestor <Suspense> -> uncaught suspend
// - Using use() with a non-thenable, non-context -> runtime error
// - Mixing useContext + use() habits in one codebase

Why it matters

use() is React 19 hook for promises and contexts. With , it turns async into declarative loading; with contexts, it removes the top-level rule. The trick is stable promise references — pair with a framework cache or memoise.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// React 19+
const data = use(somePromise);
const theme = use(ThemeContext);
Try it Yourself »

Discussion

Loading…