restate / v1.0.0
Estado que pertenece a un componente
Da a cada documento, diálogo o petición sus propios stores, que se crean con el componente y se liberan tras su desmontaje.
En esta página
useRestateScopeReglas de la factoríaValores iniciales desde propsRenderizado en servidorEspera los datos guardados de un documentoPruébaloDueños fuera de ReactuseRestateScope
La factoría declara stores y los devuelve. restate conserva el resultado entre renders y destruye el scope tras desmontarse el componente. No hay que escribir ninguna función de cierre ni efecto de limpieza.
Dos elementos Document tienen estado independiente. Para compartir un documento con sus hijos, pasa los hooks devueltos por props o por tu propio contexto.
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>
);
}Reglas de la factoría
React puede llamar a la factoría más de una vez y descartar resultados, así que mantenla síncrona y pura.
- Declara los stores en la factoría; llama a los hooks devueltos en el nivel superior del componente.
- Las props iniciales se leen una vez, como en un inicializador de useState.
- Dale una key al componente cuando otro documento necesite estado nuevo.
- Sin factoría, useRestateScope() devuelve un scope estable para stores que crees más tarde, en efectos o manejadores.
Valores iniciales desde props
Usa las props como valores iniciales y una key de React para empezar de cero con otro documento.
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} />;Renderizado en servidor
Carga los datos en tu ruta del servidor y pásalos como prop. El valor inicial también sirve de snapshot del servidor. En el App Router de Next.js, este hook va en un Client Component, que también se renderiza en el servidor.
'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>;
}Espera los datos guardados de un documento
Los stores guardados de un scope empiezan a restaurarse cuando el componente se confirma en el cliente y no forman parte del restateManager.ready global. Espera al manager.ready propio del scope en un límite de carga.
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} />;
}Pruébalo
Abre y cierra documentos y mira cómo su estado empieza de cero.
Preparando el ejemplo…
Dueños fuera de React
Cuando el estado pertenece a un servicio o a una petición del servidor, crea tú el scope y llama a destroy() al terminar. Destruir un scope nunca borra registros guardados.
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(),
};
}