Spec-Zone.ru › React

resume

resume передает предварительно отрендеренное дерево React потоком в Readable Web Stream.

const stream = await resume(reactNode, postponedState, options?)
  • Справочник
    • resume(node, postponedState, options?)
  • Использование
    • Возобновление пререндеринга
    • Дополнительные материалы

Примечание

Этот API зависит от Web Streams. Для Node.js используйте вместо этого resumeToNodeStream.


Справочник

resume(node, postponedState, options?)

Вызовите resume, чтобы возобновить рендеринг предварительно отрендеренного дерева React в виде HTML в Readable Web Stream.

import { resume } from 'react-dom/server';
import {getPostponedState} from './storage';

async function handler(request, writable) {
  const postponed = await getPostponedState(request);
  const resumeStream = await resume(<App />, postponed);
  return resumeStream.pipeTo(writable)
}

См. другие примеры ниже.

Параметры

  • reactNode: Узел React, с которым вы вызывали prerender. Например, JSX-элемент вида <App />. Ожидается, что он представляет весь документ, поэтому компонент App должен рендерить тег <html>.
  • postponedState: Непрозрачный объект postpone, возвращенный из API пререндеринга, загруженный из места его хранения (например, redis, файл или S3).
  • необязательно options: Объект с параметрами потоковой передачи.
    • необязательно nonce: Строка nonce для разрешения скриптов согласно script-src Content-Security-Policy.
    • необязательно signal: Сигнал отмены, который позволяет вам прервать серверный рендеринг и отрендерить остальное на клиенте.
    • необязательно onError: Функция обратного вызова, которая срабатывает при любой ошибке сервера, как восстановимой, так и нет. По умолчанию она вызывает только console.error. Если вы переопределяете её, чтобы логировать отчеты о сбоях, убедитесь, что вы по-прежнему вызываете console.error.

Возвращаемое значение

resume возвращает Promise:

  • Если resume успешно создал оболочку (shell), этот Promise разрешится в Readable Web Stream, который можно перенаправить в Writable Web Stream.
  • Если в оболочке произойдет ошибка, Promise будет отклонен с этой ошибкой.

Возвращаемый поток имеет дополнительное свойство:

  • allReady: Promise, который разрешается по завершении всего рендеринга. Вы можете выполнить await stream.allReady перед возвратом ответа для поисковых роботов и статической генерации. В этом случае вы не получите прогрессивной загрузки. Поток будет содержать окончательный HTML.

Важные особенности

  • resume не принимает параметры для bootstrapScripts, bootstrapScriptContent или bootstrapModules. Вместо этого вам необходимо передать эти параметры в вызов prerender, который генерирует postponedState. Вы также можете внедрить содержимое bootstrap в записываемый поток вручную.
  • resume не принимает identifierPrefix, поскольку префикс должен быть одинаковым как в prerender, так и в resume.
  • Поскольку nonce нельзя передать в prerender, следует указывать nonce в resume только в том случае, если вы не передаете скрипты в prerender.
  • resume выполняет повторный рендеринг от корня до тех пор, пока не найдет компонент, который не был полностью предварительно отрендерен. Полностью пропускаются только те компоненты, пререндеринг которых был завершен целиком (сам компонент и его дочерние элементы).

Использование

Возобновление пререндеринга

import {
  flushReadableStreamToFrame,
  getUser,
  Postponed,
  sleep,
} from "./demo-helpers";
import { StrictMode, Suspense, use, useEffect } from "react";
import { prerender } from "react-dom/static";
import { resume } from "react-dom/server";
import { hydrateRoot } from "react-dom/client";

function Header() {
  return <header>Me and my descendants can be prerendered</header>;
}

const { promise: cookies, resolve: resolveCookies } = Promise.withResolvers();

function Main() {
  const { sessionID } = use(cookies);
  const user = getUser(sessionID);

  useEffect(() => {
    console.log("reached interactivity!");
  }, []);

  return (
    <main>
      Hello, {user.name}!
      <button onClick={() => console.log("hydrated!")}>
        Clicking me requires hydration.
      </button>
    </main>
  );
}

function Shell({ children }) {
  // In a real app, this is where you would put your html and body.
  // We're just using tags here we can include in an existing body for demonstration purposes
  return (
    <html>
      <body>{children}</body>
    </html>
  );
}

function App() {
  return (
    <Shell>
      <Suspense fallback="loading header">
        <Header />
      </Suspense>
      <Suspense fallback="loading main">
        <Main />
      </Suspense>
    </Shell>
  );
}

async function main(frame) {
  // Layer 1
  const controller = new AbortController();
  const prerenderedApp = prerender(<App />, {
    signal: controller.signal,
    onError(error) {
      if (error instanceof Postponed) {
      } else {
        console.error(error);
      }
    },
  });
  // We're immediately aborting in a macrotask.
  // Any data fetching that's not available synchronously, or in a microtask, will not have finished.
  setTimeout(() => {
    controller.abort(new Postponed());
  });

  const { prelude, postponed } = await prerenderedApp;
  await flushReadableStreamToFrame(prelude, frame);

  // Layer 2
  // Just waiting here for demonstration purposes.
  // In a real app, the prelude and postponed state would've been serialized in Layer 1 and Layer would deserialize them.
  // The prelude content could be flushed immediated as plain HTML while
  // React is continuing to render from where the prerender left off.
  await sleep(2000);

  // You would get the cookies from the incoming HTTP request
  resolveCookies({ sessionID: "abc" });

  const stream = await resume(<App />, postponed);

  await flushReadableStreamToFrame(stream, frame);

  // Layer 3
  // Just waiting here for demonstration purposes.
  await sleep(2000);

  hydrateRoot(frame.contentWindow.document, <App />);
}

main(document.getElementById("container"));

Дополнительные материалы

Возобновление работает аналогично renderToReadableStream. Другие примеры можно найти в разделе использования renderToReadableStream. Раздел использования prerender содержит примеры того, как использовать конкретно prerender.

© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://react.dev/reference/react-dom/server/resume

Spec-Zone.ru

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