use
é uma API do React que permite que você leia o valor de um recurso como uma Promise ou um contexto.
const value = use(resource);
Referência
use(resource)
Chame use
em seu componente para ler o valor de um recurso como uma Promise ou contexto.
import { use } from 'react';
function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
const theme = use(ThemeContext);
// ...
Ao contrário dos React Hooks, use
pode ser chamado dentro de loops e instruções condicionais como if
. Como os React Hooks, a função que chama use
deve ser um Componente ou Hook.
Quando chamado com uma Promise, a API use
se integra com Suspense
e error boundaries. O componente que chama use
suspende enquanto a Promise passada para use
está pendente. Se o componente que chama use
for encapsulado em um limite Suspense, o fallback será exibido. Uma vez que a Promise for resolvida, o fallback Suspense é substituído pelos componentes renderizados usando os dados retornados pela API use
. Se a Promise passada para use
for rejeitada, o fallback do Error Boundary mais próximo será exibido.
Parâmetros
resource
: esta é a fonte dos dados de onde você deseja ler um valor. Um recurso pode ser uma Promise ou um contexto.
Retornos
A API use
retorna o valor que foi lido do recurso, como o valor resolvido de uma Promise ou contexto.
Ressalvas
- A API
use
deve ser chamada dentro de um Componente ou um Hook. - Ao buscar dados em um Server Component, prefira
async
eawait
em vez deuse
.async
eawait
retomam a renderização do ponto em queawait
foi invocado, enquantouse
renderiza novamente o componente após os dados serem resolvidos. - Prefira criar Promises em Server Components e passá-las para Client Components em vez de criar Promises em Client Components. Promises criadas em Client Components são recriadas a cada renderização. Promises passadas de um Server Component para um Client Component são estáveis em todas as re-renderizações. Veja este exemplo.
Uso
Lendo o contexto com use
Quando um contexto é passado para use
, ele funciona de forma semelhante a useContext
. Enquanto useContext
deve ser chamado no nível superior do seu componente, use
pode ser chamado dentro de condicionais como if
e loops como for
. use
é preferível a useContext
porque é mais flexível.
import { use } from 'react';
function Button() {
const theme = use(ThemeContext);
// ...
use
retorna o valor do contexto para o contexto que você passou. Para determinar o valor do contexto, o React pesquisa na árvore de componentes e encontra o provider de contexto mais próximo acima para aquele contexto específico.
Para passar o contexto para um Button
, envolva-o ou um de seus componentes pai no provider de contexto correspondente.
function MyPage() {
return (
<ThemeContext.Provider value="dark">
<Form />
</ThemeContext.Provider>
);
}
function Form() {
// ... renders buttons inside ...
}
Não importa quantas camadas de componentes existam entre o provider e o Button
. Quando um Button
em qualquer lugar dentro de Form
chama use(ThemeContext)
, ele receberá "dark"
como o valor.
Ao contrário de useContext
, use
pode ser chamado em condicionais e loops como if
.
function HorizontalRule({ show }) {
if (show) {
const theme = use(ThemeContext);
return <hr className={theme} />;
}
return false;
}
use
é chamado de dentro de uma instrução if
, permitindo que você leia condicionalmente valores de um Contexto.
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 }
Streaming de dados do servidor para o cliente
Os dados podem ser transmitidos do servidor para o cliente passando uma Promise como uma prop de um Server Component para um Client Component.
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>
);
}
O Client Component então pega a Promise que recebeu como prop e a passa para a API use
. Isso permite que o Client Component leia o valor da Promise que foi inicialmente criada pelo Server Component.
// message.js
'use client';
import { use } from 'react';
export function Message({ messagePromise }) {
const messageContent = use(messagePromise);
return <p>Here is the message: {messageContent}</p>;
}
Como o Message
é encapsulado em Suspense
, o fallback será exibido até que a Promise seja resolvida. Quando a Promise for resolvida, o valor será lido pela API use
e o componente Message
substituirá o fallback Suspense.
"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> ); }
Deep Dive
Uma Promise pode ser passada de um Server Component para um Client Component e resolvida no Client Component com a API use
. Você também pode resolver a Promise em um Server Component com await
e passar os dados necessários para o Client Component como uma prop.
export default async function App() {
const messageContent = await fetchMessage();
return <Message messageContent={messageContent} />
}
Mas usar await
em um Server Component bloqueará sua renderização até que a instrução await
seja finalizada. Passar uma Promise de um Server Component para um Client Component impede que a Promise bloqueie a renderização do Server Component.
Lidando com Promises rejeitadas
Em alguns casos, uma Promise passada para use
pode ser rejeitada. Você pode lidar com Promises rejeitadas de duas formas:
- Exibir um erro para os usuários com um error boundary.
- Fornecer um valor alternativo com
Promise.catch
Exibindo um erro para os usuários com um error boundary
Se você deseja exibir um erro para seus usuários quando uma Promise é rejeitada, pode usar um error boundary. Para usar um error boundary, envolva o componente onde você está chamando a API use
em um error boundary. Se a Promise passada para use
for rejeitada, o fallback para o error boundary será exibido.
"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>; }
Fornecendo um valor alternativo com Promise.catch
Se você deseja fornecer um valor alternativo quando a Promise passada para use
é rejeitada, você pode usar o método catch
da Promise.
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>
);
}
Para usar o método catch
da Promise, chame catch
no objeto Promise. catch
recebe um único argumento: uma função que recebe uma mensagem de erro como um argumento. Qualquer coisa que for retornada pela função passada para catch
será usada como o valor resolvido da Promise.
Solução de problemas
“Suspense Exception: This is not a real error!”
Você está chamando use
fora de um Componente ou função Hook do React, ou chamando use
em um bloco try-catch. Se você estiver chamando use
dentro de um bloco try-catch, envolva seu componente em um error boundary, ou chame o catch
da Promise para capturar o erro e resolver a Promise com outro valor. Veja estes exemplos.
Se você estiver chamando use
fora de um Componente ou função Hook do React, mova a chamada use
para um Componente ou função Hook do React.
function MessageComponent({messagePromise}) {
function download() {
// ❌ a função que chama `use` não é um Componente ou Hook
const message = use(messagePromise);
// ...
Em vez disso, chame use
fora de quaisquer fechamentos de componente, onde a função que chama use
é um Componente ou Hook.
function MessageComponent({messagePromise}) {
// ✅ `use` está sendo chamado de um componente.
const message = use(messagePromise);
// ...