restate / v1.0.0
Stav patriaci komponentu
Dajte každému dokumentu, dialógu alebo požiadavke vlastné store, ktoré vzniknú s komponentom a po jeho odpojení sa uvoľnia.
Na tejto stránke
useRestateScopePravidlá factoryPredvolené hodnoty z propsRenderovanie na serveriČakanie na uložené údaje dokumentuVyskúšajteVlastníci mimo ReactuseRestateScope
Factory deklaruje store a vráti ich. restate drží výsledok medzi rendermi a po odpojení komponentu scope zničí. Netreba písať žiadnu zatváraciu funkciu ani upratovací effect.
Dva prvky Document majú nezávislé stavy. Ak chcete dokument zdieľať s potomkami, odovzdajte vrátené hooky cez props alebo vlastný kontext.
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>
);
}Pravidlá factory
React môže factory zavolať viackrát a výsledky zahodiť, preto ju držte synchrónnu a čistú.
- Store deklarujte vo factory; vrátené hooky volajte na najvyššej úrovni komponentu.
- Počiatočné props sa čítajú raz, ako v inicializátore useState.
- Dajte komponentu key, keď iný dokument potrebuje čerstvý stav.
- Bez factory vracia useRestateScope() stabilný scope pre store, ktoré vytvoríte neskôr v effectoch alebo obsluhách.
Predvolené hodnoty z props
Použite props ako predvolené hodnoty a key Reactu, aby ste začali znova s iným dokumentom.
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} />;Renderovanie na serveri
Načítajte údaje v serverovej route a odovzdajte ich ako prop. Predvolená hodnota zároveň poskytne snímku zo servera. V App Router Next.js patrí tento hook do Client Component, ktorý sa aj tak renderuje na serveri.
'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>;
}Čakanie na uložené údaje dokumentu
Ukladané store v scope začnú obnovovať po commite komponentu na klientovi a nie sú súčasťou globálneho restateManager.ready. Počkajte na vlastné manager.ready daného scope vnútri hranice načítania.
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} />;
}Vyskúšajte
Otvárajte a zatvárajte dokumenty a sledujte, ako ich stav začína od nuly.
Príprava príkladu…
Vlastníci mimo React
Keď stav patrí službe alebo serverovej požiadavke, vytvorte scope sami a na konci zavolajte destroy(). Zničenie scope nikdy nezmaže uložené záznamy.
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(),
};
}