React use() Hook — Reading Promises and Context Conditionally
Learn how to use the use() hook in React 19 to read Promises with Suspense and read context conditionally. Covers data streaming, conditional context, and differences from useContext and await.
Detailed Explanation
The use() Hook (React 19)
use is a new hook in React 19 that breaks the traditional rules of hooks: it can be called inside conditionals and loops. It serves two purposes: reading Promises (with Suspense) and reading context conditionally.
Reading Promises
import { use, Suspense } from "react";
function UserProfile({ userPromise }: {
userPromise: Promise<{ name: string; email: string }>;
}) {
const user = use(userPromise); // Suspends until resolved
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
function App() {
// Create the Promise OUTSIDE the component
const userPromise = fetch("/api/user").then(r => r.json());
return (
<Suspense fallback={<p>Loading...</p>}>
<UserProfile userPromise={userPromise} />
</Suspense>
);
}
Conditional Context Reading
Unlike useContext, use can be called inside if statements:
function StatusIcon({ show }: { show: boolean }) {
if (show) {
const theme = use(ThemeContext);
return <Icon color={theme === "dark" ? "white" : "black"} />;
}
return null;
}
Key Differences from useContext
| Feature | useContext | use |
|---|---|---|
| Conditional calls | No | Yes |
| Inside loops | No | Yes |
| Reads Promises | No | Yes |
| React version | 16.8+ | 19+ |
Critical Warning: Promise Creation
Never create a Promise inside a component and pass it to use(). This creates a new Promise on every render, which defeats Suspense caching:
// BUG: New Promise on every render
function Bad() {
const data = use(fetch("/api/data").then(r => r.json()));
}
// CORRECT: Promise created in parent or cached
function Good({ dataPromise }: { dataPromise: Promise<Data> }) {
const data = use(dataPromise);
}
Error Handling
When the Promise rejects, the nearest Error Boundary catches the error, just like rendering errors. Combine Suspense and Error Boundaries for complete loading and error handling.
Use Case
Use the use() hook for reading server-streamed data in client components, conditional context consumption, integrating Promise-based APIs with Suspense, and any scenario where you need the flexibility to call a hook conditionally.