restate / v1.0.0

Estado que pertence a um componente

Dê a cada documento, diálogo ou requisição os próprios stores, criados com o componente e liberados depois da desmontagem.

Nesta páginauseRestateScopeRegras da factoryValores iniciais a partir de propsRenderização no servidorEspere os dados salvos de um documentoExperimenteDonos fora do React

useRestateScope

A factory declara stores e os retorna. O restate guarda o resultado entre renders e destrói o scope depois que o componente é desmontado. Não há função de fechamento nem efeito de limpeza para escrever.

Dois elementos Document têm estados independentes. Para compartilhar um documento com os filhos, passe os hooks retornados por props ou pelo seu próprio contexto.

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

Regras da factory

O React pode chamar a factory mais de uma vez e descartar resultados, então mantenha-a síncrona e pura.

  • Declare os stores na factory; chame os hooks retornados no nível superior do componente.
  • As props iniciais são lidas uma vez, como num inicializador de useState.
  • Dê uma key ao componente quando outro documento precisar de estado novo.
  • Sem factory, useRestateScope() retorna um scope estável para stores que você criar depois, em efeitos ou handlers.

Valores iniciais a partir de props

Use props como valores iniciais e uma key do React para recomeçar com outro documento.

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

Renderização no servidor

Carregue os dados na sua rota do servidor e passe como prop. O valor inicial também fornece o snapshot do servidor. No App Router do Next.js, este hook fica em um Client Component, que também é renderizado no servidor.

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

Espere os dados salvos de um documento

Stores salvos em um scope começam a restaurar depois que o componente é confirmado no cliente e não fazem parte do restateManager.ready global. Espere o manager.ready do próprio scope em um limite de carregamento.

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

Experimente

Abra e feche documentos e veja o estado deles recomeçar.

Preparando o exemplo…

Donos fora do React

Quando um serviço ou uma requisição do servidor é dono do estado, crie o scope você mesmo e chame destroy() ao terminar. Destruir um scope nunca apaga registros salvos.

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

Pesquisar na documentação

Pesquisa em títulos, descrições e texto de todos os guias.