restate / v1.0.0
Stan należący do komponentu
Daj każdemu dokumentowi, oknu dialogowemu czy żądaniu własne magazyny, tworzone z komponentem i zwalniane po jego odmontowaniu.
Na tej stronie
useRestateScopeZasady fabrykiWartości początkowe z propsRenderowanie na serwerzePoczekaj na zapisane dane dokumentuWypróbujWłaściciele poza ReactuseRestateScope
Fabryka deklaruje magazyny i je zwraca. restate przechowuje wynik między renderami i niszczy zakres po odmontowaniu komponentu. Nie trzeba pisać funkcji zamykającej ani efektu sprzątającego.
Dwa elementy Document mają niezależne stany. Aby udostępnić dokument dzieciom, przekaż zwrócone hooki przez props lub własny 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>
);
}Zasady fabryki
React może wywołać fabrykę więcej niż raz i odrzucić wyniki, więc niech będzie synchroniczna i czysta.
- Deklaruj magazyny w fabryce; wywołuj zwrócone hooki na najwyższym poziomie komponentu.
- Początkowe props są odczytywane raz, jak w inicjalizatorze useState.
- Nadaj komponentowi key, gdy inny dokument potrzebuje świeżego stanu.
- Bez fabryki useRestateScope() zwraca stabilny zakres dla magazynów, które utworzysz później w efektach lub obsłudze zdarzeń.
Wartości początkowe z props
Użyj props jako wartości początkowych, a key w React, by zacząć od nowa z innym dokumentem.
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} />;Renderowanie na serwerze
Wczytaj dane w trasie serwera i przekaż je jako prop. Wartość początkowa służy też jako migawka serwera. W App Router Next.js ten hook trafia do Client Component, który i tak jest renderowany na serwerze.
'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>;
}Poczekaj na zapisane dane dokumentu
Zapisywane magazyny w zakresie zaczynają przywracanie po zatwierdzeniu komponentu po stronie klienta i nie są częścią globalnego restateManager.ready. Poczekaj na własny manager.ready zakresu wewnątrz granicy ładowania.
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} />;
}Wypróbuj
Otwieraj i zamykaj dokumenty i patrz, jak ich stan zaczyna się od zera.
Przygotowywanie przykładu…
Właściciele poza React
Gdy stan należy do usługi lub żądania na serwerze, utwórz zakres samodzielnie i na końcu wywołaj destroy(). Zniszczenie zakresu nigdy nie usuwa zapisanych rekordów.
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(),
};
}