use
use
is a React API that lets you read the value of a resource like a Promise or context.
const value = use(resource);
Reference {/reference/}
use(resource)
{/use/}
Call use
in your component to read the value of a resource like a Promise or context.
import { use } from 'react';
function MessageComponent({ messagePromise }) { const message = use(messagePromise); const theme = use(ThemeContext); // ...
Unlike React Hooks, use
can be called within loops and conditional statements like if
. Like React Hooks, the function that calls use
must be a Component or Hook.
When called with a Promise, the use
API integrates with Suspense
and error boundaries. The component calling use
suspends while the Promise passed to use
is pending. If the component that calls use
is wrapped in a Suspense boundary, the fallback will be displayed. Once the Promise is resolved, the Suspense fallback is replaced by the rendered components using the data returned by the use
API. If the Promise passed to use
is rejected, the fallback of the nearest Error Boundary will be displayed.
Parameters {/parameters/}
resource
: this is the source of the data you want to read a value from. A resource can be a Promise or a context.
Returns {/returns/}
The use
API returns the value that was read from the resource like the resolved value of a Promise or context.
Caveats {/caveats/}
- The
use
API must be called inside a Component or a Hook. - When fetching data in a Server Component, prefer
async
andawait
overuse
.async
andawait
pick up rendering from the point whereawait
was invoked, whereasuse
re-renders the component after the data is resolved. - Prefer creating Promises in Server Components and passing them to Client Components over creating Promises in Client Components. Promises created in Client Components are recreated on every render. Promises passed from a Server Component to a Client Component are stable across re-renders. See this example.
Usage {/usage/}
Reading context with use
{/reading-context-with-use/}
When a context is passed to use
, it works similarly to useContext
. While useContext
must be called at the top level of your component, use
can be called inside conditionals like if
and loops like for
. use
is preferred over useContext
because it is more flexible.
import { use } from 'react';
function Button() { const theme = use(ThemeContext); // ...
use
returns the
To pass context to a Button
, wrap it or one of its parent components into the corresponding context provider.
function MyPage() { return ( <ThemeContext.Provider value="dark"> <Form /> </ThemeContext.Provider> );}
function Form() { // ... renders buttons inside ...}
It doesn’t matter how many layers of components there are between the provider and the Button
. When a Button
anywhere inside of Form
calls use(ThemeContext)
, it will receive "dark"
as the value.
Unlike useContext
, use
if
function HorizontalRule({ show }) { if (show) { const theme = use(ThemeContext); return <hr className={theme} />; } return false;}
use
if
Like useContext
, use(context)
always looks for the closest context provider above the component that calls it. It searches upwards and does not consider context providers in the component from which you’re calling use(context)
.
import { createContext, use } from 'react';
const ThemeContext = createContext(null);
export default function MyApp() { return ( <ThemeContext.Provider value="dark"> <Form /> </ThemeContext.Provider> )}
function Form() { return ( <Panel title="Welcome"> <Button show={true}>Sign up</Button> <Button show={false}>Log in</Button> </Panel> );}
function Panel({ title, children }) { const theme = use(ThemeContext); const className = 'panel-' + theme; return ( <section className={className}> <h1>{title}</h1> {children} </section> )}
function Button({ show, children }) { if (show) { const theme = use(ThemeContext); const className = 'button-' + theme; return ( <button className={className}> {children} </button> ); } return false}
.panel-light,.panel-dark { border: 1px solid black; border-radius: 4px; padding: 20px;}.panel-light { color: #222; background: #fff;}
.panel-dark { color: #fff; background: rgb(23, 32, 42);}
.button-light,.button-dark { border: 1px solid #777; padding: 5px; margin-right: 10px; margin-top: 10px;}
.button-dark { background: #222; color: #fff;}
.button-light { background: #fff; color: #222;}
Streaming data from the server to the client {/streaming-data-from-server-to-client/}
Data can be streamed from the server to the client by passing a Promise as a prop from a
import { fetchMessage } from './lib.js';import { Message } from './message.js';
export default function App() { const messagePromise = fetchMessage(); return ( <Suspense fallback={<p>waiting for message...</p>}> <Message messagePromise={messagePromise} /> </Suspense> );}
The use
'use client';
import { use } from 'react';
export function Message({ messagePromise }) { const messageContent = use(messagePromise); return <p>Here is the message: {messageContent}</p>;}
Because Message
Suspense
use
Message
"use client";
import { use, Suspense } from "react";
function Message({ messagePromise }) { const messageContent = use(messagePromise); return <p>Here is the message: {messageContent}</p>;}
export function MessageContainer({ messagePromise }) { return ( <Suspense fallback={<p>⌛Downloading message...</p>}> <Message messagePromise={messagePromise} /> </Suspense> );}
import { useState } from "react";import { MessageContainer } from "./message.js";
function fetchMessage() { return new Promise((resolve) => setTimeout(resolve, 1000, "⚛️"));}
export default function App() { const [messagePromise, setMessagePromise] = useState(null); const [show, setShow] = useState(false); function download() { setMessagePromise(fetchMessage()); setShow(true); }
if (show) { return <MessageContainer messagePromise={messagePromise} />; } else { return <button onClick={download}>Download message</button>; }}
import React, { StrictMode } from 'react';import { createRoot } from 'react-dom/client';import './styles.css';
// TODO: update this example to use// the Codesandbox Server Component// demo environment once it is createdimport App from './App';
const root = createRoot(document.getElementById('root'));root.render( <StrictMode> <App /> </StrictMode>);
When passing a Promise from a Server Component to a Client Component, its resolved value must be serializable to pass between server and client. Data types like functions aren’t serializable and cannot be the resolved value of such a Promise.
Should I resolve a Promise in a Server or Client Component? {/resolve-promise-in-server-or-client-component/}
A Promise can be passed from a Server Component to a Client Component and resolved in the Client Component with the use
API. You can also resolve the Promise in a Server Component with await
and pass the required data to the Client Component as a prop.
export default async function App() { const messageContent = await fetchMessage(); return <Message messageContent={messageContent} />}
But using await
in a Server Component will block its rendering until the await
statement is finished. Passing a Promise from a Server Component to a Client Component prevents the Promise from blocking the rendering of the Server Component.
Dealing with rejected Promises {/dealing-with-rejected-promises/}
In some cases a Promise passed to use
could be rejected. You can handle rejected Promises by either:
- Displaying an error to users with an error boundary.
- Providing an alternative value with
Promise.catch
Displaying an error to users with an error boundary {/displaying-an-error-to-users-with-error-boundary/}
If you’d like to display an error to your users when a Promise is rejected, you can use an error boundary. To use an error boundary, wrap the component where you are calling the use
API in an error boundary. If the Promise passed to use
is rejected the fallback for the error boundary will be displayed.
"use client";
import { use, Suspense } from "react";import { ErrorBoundary } from "react-error-boundary";
export function MessageContainer({ messagePromise }) { return ( <ErrorBoundary fallback={<p>⚠️Something went wrong</p>}> <Suspense fallback={<p>⌛Downloading message...</p>}> <Message messagePromise={messagePromise} /> </Suspense> </ErrorBoundary> );}
function Message({ messagePromise }) { const content = use(messagePromise); return <p>Here is the message: {content}</p>;}
import { useState } from "react";import { MessageContainer } from "./message.js";
function fetchMessage() { return new Promise((resolve, reject) => setTimeout(reject, 1000));}
export default function App() { const [messagePromise, setMessagePromise] = useState(null); const [show, setShow] = useState(false); function download() { setMessagePromise(fetchMessage()); setShow(true); }
if (show) { return <MessageContainer messagePromise={messagePromise} />; } else { return <button onClick={download}>Download message</button>; }}
import React, { StrictMode } from 'react';import { createRoot } from 'react-dom/client';import './styles.css';
// TODO: update this example to use// the Codesandbox Server Component// demo environment once it is createdimport App from './App';
const root = createRoot(document.getElementById('root'));root.render( <StrictMode> <App /> </StrictMode>);
{ "dependencies": { "react": "19.0.0", "react-dom": "19.0.0", "react-scripts": "^5.0.0", "react-error-boundary": "4.0.3" }, "main": "/index.js"}
Providing an alternative value with Promise.catch
{/providing-an-alternative-value-with-promise-catch/}
If you’d like to provide an alternative value when the Promise passed to use
is rejected you can use the Promise’s catch
import { Message } from './message.js';
export default function App() { const messagePromise = new Promise((resolve, reject) => { reject(); }).catch(() => { return "no new message found."; });
return ( <Suspense fallback={<p>waiting for message...</p>}> <Message messagePromise={messagePromise} /> </Suspense> );}
To use the Promise’s catch
catch
catch
catch
Troubleshooting {/troubleshooting/}
“Suspense Exception: This is not a real error!” {/suspense-exception-error/}
You are either calling use
outside of a React Component or Hook function, or calling use
in a try–catch block. If you are calling use
inside a try–catch block, wrap your component in an error boundary, or call the Promise’s catch
to catch the error and resolve the Promise with another value. See these examples.
If you are calling use
outside a React Component or Hook function, move the use
call to a React Component or Hook function.
function MessageComponent({messagePromise}) { function download() { // ❌ the function calling `use` is not a Component or Hook const message = use(messagePromise); // ...
Instead, call use
outside any component closures, where the function that calls use
is a Component or Hook.
function MessageComponent({messagePromise}) { // ✅ `use` is being called from a component. const message = use(messagePromise); // ...