use
Canary
API use в настоящее время доступен только в каналах Canary и экспериментальных каналах React. Дополнительные сведения о каналах выпуска React см. здесь.
use — это API React, позволяющий считывать значение ресурса, например, Promise или контекст.
const value = use(resource);
Справочник
use(resource)
Вызовите use в своем компоненте, чтобы прочитать значение ресурса, например, Promise или контекст.
import { use } from 'react';
function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
const theme = use(ThemeContext);
// ... В отличие от хуков React, use можно вызывать внутри циклов и условных операторов, например, if. Как и хуки React, функция, которая вызывает use, должна быть компонентом или хуком.
При вызове с Promise API use интегрируется с Suspense и ограничителями ошибок. Компонент, вызывающий use, приостанавливается, пока Promise, переданный в use, ожидает выполнения. Если компонент, вызывающий use, обернут в ограничитель Suspense, отобразится резервный вариант. После разрешения Promise резервный вариант Suspense заменяется рендерными компонентами, использующими данные, возвращаемые API use. Если Promise, переданный в use, отклоняется, отобразится резервный вариант ближайшего ограничителя ошибок.
См. дополнительные примеры ниже.
Параметры
-
resource: это источник данных, значение которого вы хотите прочитать. Ресурс может быть Promise или контекстом.
Возвращаемое значение
API use возвращает значение, считанное из ресурса, например, разрешенное значение Promise или контекста.
Ограничения
- API
useдолжен вызываться внутри компонента или хука. - При получении данных в компоненте сервера предпочтительнее использовать
asyncиawaitвместоuse.asyncиawaitвозобновляют рендеринг с того момента, когда был вызванawait, в то время какuseповторно рендерит компонент после разрешения данных. - Предпочтительнее создавать Promise в компонентах сервера и передавать их в компоненты клиента, чем создавать Promise в компонентах клиента. Promise, созданные в компонентах клиента, пересоздаются при каждом рендеринге. Promise, переданные из компонента сервера в компонент клиента, остаются стабильными при повторном рендеринге. См. этот пример.
Использование
Чтение контекста с помощью use
Когда контекст передаётся в use, он работает аналогично useContext. В то время как useContext должен вызываться на верхнем уровне вашего компонента, use может вызываться внутри условных выражений, например, if, и циклов, например, for. use предпочтительнее useContext, потому что он более гибкий.
import { use } from 'react';
function Button() {
const theme = use(ThemeContext);
// ... use возвращает значение контекста для контекста, который вы передали. Для определения значения контекста React ищет компонент в дереве и находит наиболее близкий контекст-провайдер выше для этого конкретного контекста.
Чтобы передать контекст в Button, оберните его или один из его родительских компонентов в соответствующий поставщик контекста.
function MyPage() {
return (
<ThemeContext.Provider value="dark">
<Form />
</ThemeContext.Provider>
);
}
function Form() {
// ... renders buttons inside ...
} Не имеет значения, сколько слоёв компонентов находится между поставщиком и Button. Когда Button в любом месте внутри Form вызывает use(ThemeContext), он получит "dark" в качестве значения.
В отличие от useContext, use может вызываться в условных операторах и циклах, например, if.
function HorizontalRule({ show }) {
if (show) {
const theme = use(ThemeContext);
return <hr className={theme} />;
}
return false;
} use вызывается изнутри оператора if, позволяя вам условно читать значения из контекста.
Подводные камни
Как и useContext, use(context) всегда ищет ближайшего поставщика контекста выше компонента, который его вызывает. Он ищет вверх и не рассматривает поставщиков контекста в компоненте, из которого вы вызываете 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 }
Потоковая передача данных с сервера на клиент
Данные можно передавать с сервера на клиент, передавая Promise в качестве свойства от компонента сервера к компоненту клиента.
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>
);
} Затем компонент клиента принимает Promise, полученный в качестве свойства, и передает его в API use. Это позволяет компоненту клиента прочитать значение из Promise, который изначально был создан компонентом сервера.
// message.js
'use client';
import { use } from 'react';
export function Message({ messagePromise }) {
const messageContent = use(messagePromise);
return <p>Here is the message: {messageContent}</p>;
} Поскольку Message обернут в Suspense, пока Promise не будет разрешен, отобразится резервный вариант. Когда Promise разрешен, значение будет прочитано API use, и компонент Message заменит резервный вариант 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> ); }
Примечание
При передаче Promise из компонента сервера в компонент клиента его разрешенное значение должно быть сериализуемым для передачи между сервером и клиентом. Такие типы данных, как функции, не сериализуемы и не могут быть разрешенным значением такого Promise.
Подробный анализ
Разрешить Promise в компоненте сервера или клиента?
Promise можно передать из компонента сервера в компонент клиента и разрешить в компоненте клиента с помощью API use. Вы также можете разрешить Promise в компоненте сервера с помощью await и передать необходимые данные в компонент клиента в качестве свойства.
export default async function App() {
const messageContent = await fetchMessage();
return <Message messageContent={messageContent} />
}
Но использование await в компоненте сервера заблокирует его рендеринг до тех пор, пока оператор await не будет завершён. Передача Promise из компонента сервера в компонент клиента предотвращает блокирование рендеринга компонента сервера.
Обработка отклоненных Promise
В некоторых случаях Promise, переданный в use, может быть отклонен. Вы можете обработать отклоненные Promise, выполнив следующие действия:
- Отображение ошибки пользователям с помощью ограничителя ошибок.
- Предоставление альтернативного значения с помощью
Promise.catch
Подводные камни
use не может вызываться в блоке try-catch. Вместо блока try-catch оберните свой компонент в ограничитель ошибок или предоставьте альтернативное значение для использования с методом .catch Promise.
Отображение ошибки пользователям с помощью ограничителя ошибок
Если вы хотите отобразить ошибку пользователю при отклонении Promise, вы можете использовать ограничитель ошибок. Для использования ограничителя ошибок оберните компонент, где вы вызываете API use, в ограничитель ошибок. Если Promise, переданный в use, отклоняется, отобразится резервный вариант ограничителя ошибок.
"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>; }
Предоставление альтернативного значения с помощью Promise.catch
Если вы хотите предоставить альтернативное значение при отклонении Promise, переданного в use, вы можете использовать метод Promise 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>
);
} Чтобы использовать метод catch Promise, вызовите catch на объекте Promise. catch принимает один аргумент: функцию, которая принимает сообщение об ошибке в качестве аргумента. Всё, что возвращается функцией, переданной в catch, будет использоваться в качестве разрешённого значения Promise.
Отладка
“Исключение Suspense: Это не реальная ошибка!”
Вы либо вызываете use вне функции компонента или хука React, либо вызываете use в блоке try–catch. Если вы вызываете use внутри блока try–catch, оберните свой компонент в ограничитель ошибок или вызовите метод catch Promise для перехвата ошибки и разрешения Promise с другим значением. См. примеры.
Если вы вызываете use вне функции компонента или хука React, перенесите вызов use в функцию компонента или хука React.
function MessageComponent({messagePromise}) {
function download() {
// ❌ the function calling `use` is not a Component or Hook
const message = use(messagePromise);
// ... Вместо этого, вызывайте use вне любых замыканий компонента, где функция, вызывающая use, является компонентом или хуком.
function MessageComponent({messagePromise}) {
// ✅ `use` is being called from a component.
const message = use(messagePromise);
// ...
© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://18.react.dev/reference/react/use