use
Reads the value of a promise or a context during render, including inside conditions and loops.
const value = use(resource)- Added in React 19.0.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$resource | Promise<T> | Context<T> | The source of the value you want to read. A promise whose resolved value you want — it must be cached so the same instance is reused across re-renders — or a context created with createContext. |
Return value
TFor a context: the context value from the closest provider above the calling component, or the defaultValue passed to createContext if there is no provider. For a promise: the resolved value of the promise.
Errors
A rejected promise throws its rejection reason, which is caught by the nearest Error Boundary; `use` cannot be called inside a try/catch block.
Changelog
- PHP 19.0.0Introduced. Reads a promise or a Context in render, and unlike Hooks may be called conditionally and inside loops.
use reads a resource during render. Hand it a promise and the component suspends until the promise settles; hand it a context and you get the nearest provider's value. Despite the name it is not a Hook: it may be called inside if blocks, loops and after early returns — the one React API for which the rules of Hooks do not apply.
When to reach for it
The primary use is a promise created on the server and passed to a Client Component: the server starts the work, the client unwraps it under a <Suspense> boundary, and no loading state has to be modelled in state. The secondary use is conditional context — reading a theme only when a flag is set, or after an early return, which useContext forbids.
The caching rule
The promise identity must survive re-renders. Creating one in a Client Component's render body produces a new promise each time, so the component suspends forever and React warns about an uncached promise. Create it in a Server Component, in a framework cache, in module scope, or in state — never inline. Errors surface differently too: use cannot sit inside try/catch, so a rejection must be handled by an Error Boundary above the component.
Example
When to use it
- Unwrap a promise a Server Component passed to a Client Component, with <Suspense> supplying the loading UI.
- Read a context value inside an if branch or after an early return, where useContext cannot be called.
- Read one of several contexts chosen at runtime, inside a loop over a list of context objects.
Frequently asked questions
Is use a Hook?
No — despite the name, use is not a Hook and the rules of Hooks do not apply to it. It can be called inside conditionals, loops and after early returns. It still has to be called from inside a component or a Hook, and it cannot be called inside a try/catch block.
Why does my component suspend forever with use?
Because a new promise is created on every render, usually by calling a fetch helper directly in the component body. React suspends, re-renders, sees a different promise and suspends again. Create the promise outside render — in a Server Component, a framework-level cache, module scope, or state — so the same instance is returned each time.
Can I use use instead of useContext everywhere?
Yes for Client Components — use(SomeContext) returns the same value as useContext(SomeContext) and additionally works conditionally. Reading context with use is not supported in Server Components, and useContext remains fine for the common unconditional read at the top of a component.
More examples
Server Component starts the request, Client Component unwraps it
The page renders and streams before the comments resolve; the fallback appears in their place and is replaced when the promise settles. Because the promise is created in the Server Component, it is stable across the client's re-renders — this is the shape use was designed for. The resolved value must be serializable to cross the server/client boundary.
// app/page.jsx — Server Component
import { Suspense } from "react";
import Comments from "./Comments.jsx";
export default function Page() {
// No await here: the promise is passed down, so the shell streams immediately.
const commentsPromise = fetchComments();
return (
<Suspense fallback={<p>Loading comments…</p>}>
<Comments commentsPromise={commentsPromise} />
</Suspense>
);
}
// app/Comments.jsx — Client Component
"use client";
import { use } from "react";
export default function Comments({ commentsPromise }) {
const comments = use(commentsPromise);
return (
<ul>
{comments.map(comment => (
<li key={comment.id}>{comment.text}</li>
))}
</ul>
);
}Rejections need an Error Boundary, not try/catch
The pane shows "Error: Could not load albums". The rejection is thrown out of render, past the Suspense boundary, and is caught by the error boundary — Suspense only handles the pending state, never the failed one. Wrapping the use call in try/catch is explicitly unsupported because React needs to re-throw the thrown value to suspend.
import { Component, Suspense, use } from "react";
const failingPromise = Promise.reject(new Error("Could not load albums"));
// Attach a no-op handler so the rejection is not reported as unhandled
// before React reads it during render.
failingPromise.catch(() => {});
function Albums() {
// ❌ Not allowed: `use` cannot be called inside a try/catch block.
// try { const albums = use(failingPromise); } catch (e) { ... }
const albums = use(failingPromise);
return <p>{albums.length} albums</p>;
}
class ErrorBoundary extends Component {
state = { error: null };
static getDerivedStateFromError(error) {
return { error };
}
render() {
return this.state.error ? (
<p>Error: {this.state.error.message}</p>
) : (
this.props.children
);
}
}
export default function App() {
return (
<ErrorBoundary>
<Suspense fallback={<p>Loading albums…</p>}>
<Albums />
</Suspense>
</ErrorBoundary>
);
}
Discussion