restate / v1.0.0
State som hører til en komponent
Gi hvert dokument, hver dialog eller forespørsel egne stores, som opprettes med komponenten og frigjøres etter unmount.
På denne siden
useRestateScopeRegler for factoryenStartverdier fra propsServerrenderingVent på lagrede data for et dokumentPrøv detEiere utenfor ReactuseRestateScope
Factoryen deklarerer stores og returnerer dem. restate tar vare på resultatet mellom renderinger og ødelegger scopet etter at komponenten er avmontert. Det finnes ingen lukkefunksjon eller oppryddings-effect å skrive.
To Document-elementer har uavhengig state. For å dele et dokument med barnekomponenter sender du de returnerte hookene 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 kalle factoryen mer enn én gang og forkaste resultatene, så hold den synkron og ren.
- Deklarer stores i factoryen; kall de returnerte hookene på øverste nivå i komponenten.
- Startprops leses én gang, som i en initialiserer til useState.
- Gi komponenten en key når et annet dokument trenger fersk state.
- Uten factory returnerer useRestateScope() et stabilt scope for stores du oppretter senere i effects eller håndterere.
Startverdier fra props
Bruk props som startverdier og en React-key for å begynne på nytt med et annet 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
Last inn data i serverruten og send dem som en prop. Startverdien gir også serverens øyeblikksbilde. I Next.js App Router hører denne hooken hjemme i en Client Component, som likevel 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å lagrede data for et dokument
Lagrede stores i et scope begynner å gjenopprette etter at komponenten er committet på klienten, og er ikke med i den globale restateManager.ready. Vent på scopets egen manager.ready innenfor en lastegrense.
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
Åpne og lukk dokumenter og se state-en deres starte på nytt.
Forbereder eksempelet …
Eiere utenfor React
Når state hører til en tjeneste eller en serverforespørsel, oppretter du scopet selv og kaller destroy() til slutt. Å ødelegge et scope sletter aldri lagrede 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(),
};
}