restate / v1.0.0

Состояние, принадлежащее компоненту

Дайте каждому документу, диалогу или запросу собственные хранилища, которые создаются вместе с компонентом и освобождаются после его размонтирования.

На этой страницеuseRestateScopeПравила фабрикиНачальные значения из propsРендеринг на сервереОжидание сохранённых данных документаПопробуйтеВладельцы вне React

useRestateScope

Фабрика объявляет хранилища и возвращает их. restate хранит результат между рендерами и уничтожает область после размонтирования компонента. Никаких функций закрытия или эффектов очистки писать не нужно.

Два элемента Document имеют независимые состояния. Чтобы передать документ дочерним компонентам, передайте возвращённые хуки через props или свой контекст.

JavaScript / JSX
import { restate, useRestateScope } from '@kkwaenggwari/restate';

function Document() {
  const { useDraft, useSelection } = useRestateScope((scope) => ({
    useDraft: restate('', { scope }),
    useSelection: restate(0, { scope }),
  }));
  const text = useDraft();
  const selection = useSelection();

  return (
    <section>
      <input value={text} onChange={(event) => useDraft.set(event.target.value)} />
      <button onClick={() => useSelection.set((n) => n + 1)}>Selection: {selection}</button>
    </section>
  );
}

Правила фабрики

React может вызывать фабрику несколько раз и отбрасывать результаты, поэтому она должна быть синхронной и чистой.

  • Объявляйте хранилища в фабрике; вызывайте возвращённые хуки на верхнем уровне компонента.
  • Начальные props читаются один раз, как в инициализаторе useState.
  • Задайте компоненту key, когда другому документу нужно новое состояние.
  • Без фабрики useRestateScope() возвращает стабильную область для хранилищ, которые вы создадите позже — в эффектах или обработчиках.

Начальные значения из props

Используйте props как начальные значения, а key React — чтобы начать заново с другим документом.

JavaScript / JSX
function Editor({ document }) {
  // The initial value is captured once, like a useState initializer.
  const useTitle = useRestateScope((scope) => restate(document.title, { scope }));
  const title = useTitle();
  return <input value={title} onChange={(event) => useTitle.set(event.target.value)} />;
}

// A different document gets fresh state.
<Editor key={document.id} document={document} />;

Рендеринг на сервере

Загрузите данные в серверном маршруте и передайте их как prop. Начальное значение служит и серверным снимком. В App Router Next.js этот хук размещается в Client Component, который всё равно рендерится на сервере.

JavaScript / JSX
'use client';

import { restate, useRestateScope } from '@kkwaenggwari/restate';

export default function Profile({ user }) {
  const useProfile = useRestateScope((scope) => restate(user, { scope }));
  const profile = useProfile();
  return <p>{profile.name}</p>;
}

Ожидание сохранённых данных документа

Сохраняемые хранилища в области начинают восстановление после коммита компонента на клиенте и не входят в глобальный restateManager.ready. Дожидайтесь собственного manager.ready области внутри границы загрузки.

JavaScript / JSX
import { useEffect, useState } from 'react';
import { persistedRestate, useRestateScope } from '@kkwaenggwari/restate';

function Document({ documentId }) {
  const { manager, useDraft } = useRestateScope((scope) => ({
    manager: scope.manager,
    useDraft: persistedRestate('', { scope, namespace: 'documents', key: documentId }),
  }));
  const [state, setState] = useState('loading');

  useEffect(() => {
    let active = true;
    manager.ready.then(
      () => active && setState('ready'),
      () => active && setState('error'),
    );
    return () => {
      active = false;
    };
  }, [manager]);

  if (state === 'error') return <p>Could not load this document.</p>;
  if (state === 'loading') return <p>Loading document…</p>;
  return <Editor useDraft={useDraft} />;
}

Попробуйте

Открывайте и закрывайте документы и смотрите, как их состояние начинается с нуля.

Подготовка примера…

Владельцы вне React

Когда состояние принадлежит сервису или серверному запросу, создайте область сами и вызовите destroy() в конце. Уничтожение области никогда не удаляет сохранённые записи.

JavaScript / JSX
import { createRestateScope, persistedRestate } from '@kkwaenggwari/restate';

export function createDocument(documentId) {
  const scope = createRestateScope();
  const useDraft = persistedRestate('', {
    scope,
    namespace: 'documents',
    key: documentId,
  });
  return {
    useDraft,
    manager: scope.manager,
    save: () => scope.manager.saveAll(),
    destroy: () => scope.destroy(),
  };
}

Поиск по документации

Поиск по заголовкам, описаниям и тексту всех руководств.