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.

Veja mais exemplos abaixo.

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 e await em vez de use. async e await retomam a renderização do ponto em que await foi invocado, enquanto use 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.

Pitfall

Como useContext, use(context) sempre procura o provider de contexto mais próximo acima do componente que o chama. Ele pesquisa para cima e não considera os providers de contexto no componente de onde você está chamando 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
}

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>
  );
}

Note

Ao passar uma Promise de um Server Component para um Client Component, seu valor resolvido deve ser serializável para passar entre o servidor e o cliente. Tipos de dados como funções não são serializáveis e não podem ser o valor resolvido de tal Promise.

Deep Dive

Devo resolver uma Promise em um Server ou Client Component?

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:

  1. Exibir um erro para os usuários com um error boundary.
  2. Fornecer um valor alternativo com Promise.catch

Pitfall

use não pode ser chamado em um bloco try-catch. Em vez de um bloco try-catch envolva seu componente em um Error Boundary, ou forneça um valor alternativo para usar com o método .catch da Promise.

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);
// ...