restate / v1.0.0
State som tillhör en komponent
Ge varje dokument, dialog eller begäran egna stores, som skapas med komponenten och släpps efter dess unmount.
På den här sidan
useRestateScopeRegler för factorynStartvärden från propsServerrenderingVänta på ett dokuments sparade dataProvaÄgare utanför ReactuseRestateScope
Factoryn deklarerar stores och returnerar dem. restate behåller resultatet mellan renderingar och förstör scopet efter att komponenten avmonterats. Det finns ingen stängningsfunktion eller städeffekt att skriva.
Två Document-element har oberoende state. För att dela ett dokument med barnkomponenter skickar du de returnerade hookarna via props eller din egen 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>
);
}Regler för factoryn
React kan anropa factoryn mer än en gång och kasta resultaten, så håll den synkron och ren.
- Deklarera stores i factoryn; anropa de returnerade hookarna på komponentens översta nivå.
- Initiala props läses en gång, som i en initialiserare till useState.
- Ge komponenten en key när ett annat dokument behöver färskt state.
- Utan factory returnerar useRestateScope() ett stabilt scope för stores som du skapar senare i effects eller hanterare.
Startvärden från props
Använd props som startvärden och en React-key för att börja om med ett annat dokument.
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} />;Serverrendering
Läs in data i serverrutten och skicka den som en prop. Startvärdet ger också serverns ögonblicksbild. I Next.js App Router hör den här hooken hemma i en Client Component, som ändå renderas på servern.
'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>;
}Vänta på ett dokuments sparade data
Sparade stores i ett scope börjar återställas efter att komponenten committats på klienten och ingår inte i den globala restateManager.ready. Vänta på scopets egen manager.ready inom en laddningsgräns.
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} />;
}Prova
Öppna och stäng dokument och se deras state börja om från noll.
Förbereder exemplet…
Ägare utanför React
När state tillhör en tjänst eller en serverbegäran skapar du scopet själv och anropar destroy() i slutet. Att förstöra ett scope raderar aldrig sparade poster.
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(),
};
}