restate / v1.0.0
State, der hører til en komponent
Giv hvert dokument, hver dialog eller anmodning sine egne stores, der oprettes med komponenten og frigives efter dens unmount.
På denne side
useRestateScopeRegler for factoryenStartværdier fra propsServerrenderingVent på et dokuments gemte dataPrøv detEjere uden for ReactuseRestateScope
Factoryen erklærer stores og returnerer dem. restate beholder resultatet mellem renderinger og nedlægger scopet, efter at komponenten er afmonteret. Der er ingen lukkefunktion eller oprydnings-effect at skrive.
To Document-elementer har uafhængig state. For at dele et dokument med børnekomponenter giver du de returnerede hooks videre via props eller din egen kontekst.
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 for factoryen
React kan kalde factoryen mere end én gang og kassere resultaterne, så hold den synkron og ren.
- Erklær stores i factoryen; kald de returnerede hooks på komponentens øverste niveau.
- Startprops læses én gang, som i en initialiserer til useState.
- Giv komponenten en key, når et andet dokument skal have frisk state.
- Uden factory returnerer useRestateScope() et stabilt scope til stores, du opretter senere i effects eller handlers.
Startværdier fra props
Brug props som startværdier og en React-key til at starte forfra med et andet 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
Indlæs data i serverruten, og giv dem videre som en prop. Startværdien giver også serverens snapshot. I Next.js App Router hører denne hook hjemme i en Client Component, som stadig renderes på serveren.
'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>;
}Vent på et dokuments gemte data
Gemte stores i et scope begynder at gendanne, efter at komponenten er committet på klienten, og indgår ikke i den globale restateManager.ready. Vent på scopets egen manager.ready inden for en indlæsningsgrænse.
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} />;
}Prøv det
Åbn og luk dokumenter, og se deres state starte forfra.
Forbereder eksemplet…
Ejere uden for React
Når state hører til en service eller en serveranmodning, opretter du selv scopet og kalder destroy() til sidst. At nedlægge et scope sletter aldrig gemte 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(),
};
}