Spec-Zone.ru › React 18

use - Эта функция доступна в последней версии Canary

Canary

API use в настоящее время доступен только в каналах Canary и экспериментальных каналах React. Дополнительные сведения о каналах выпуска React см. здесь.

use — это API React, позволяющий считывать значение ресурса, например, Promise или контекст.

const value = use(resource);
  • Справочник
    • use(resource)
  • Использование
    • Чтение контекста с помощью use
    • Потоковая передача данных с сервера на клиент
    • Обработка отклоненных Promise
  • Отладка
    • “Исключение Suspense: Это не реальная ошибка!”

Справочник

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, выполнив следующие действия:

  1. Отображение ошибки пользователям с помощью ограничителя ошибок.
  2. Предоставление альтернативного значения с помощью 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API