restate / v1.0.0
Състояние, което принадлежи на компонент
Дайте на всеки документ, диалог или заявка собствени store, които се създават с компонента и се освобождават след демонтирането му.
На тази страница
useRestateScopeПравила за factoryНачални стойности от propsРендериране на сървъраИзчакване на запазените данни на документОпитайтеСобственици извън ReactuseRestateScope
Factory декларира store и ги връща. restate пази резултата между рендерите и унищожава scope след демонтиране на компонента. Няма функция за затваряне или effect за почистване, които да пишете.
Два елемента Document имат независими състояния. За да споделите документ с дъщерни компоненти, подайте върнатите hooks чрез props или собствен контекст.
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>
);
}Правила за factory
React може да извика factory повече от веднъж и да изхвърли резултатите, затова я дръжте синхронна и чиста.
- Декларирайте store във factory; извиквайте върнатите hooks на най-горното ниво на компонента.
- Началните props се четат веднъж, както в инициализатор на useState.
- Дайте на компонента key, когато друг документ се нуждае от ново състояние.
- Без factory useRestateScope() връща стабилен scope за store, които създавате по-късно в effects или обработчици.
Начални стойности от props
Използвайте props като начални стойности и key на React, за да започнете отначало с друг документ.
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} />;Рендериране на сървъра
Заредете данните в сървърния маршрут и ги подайте като prop. Началната стойност служи и като моментна снимка от сървъра. В App Router на Next.js този hook е в Client Component, който пак се рендерира на сървъра.
'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>;
}Изчакване на запазените данни на документ
Запазваните store в scope започват възстановяване след commit на компонента в клиента и не са част от глобалния restateManager.ready. Изчакайте собствения manager.ready на scope в граница за зареждане.
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} />;
}Опитайте
Отваряйте и затваряйте документи и вижте как състоянието им започва отначало.
Подготовка на примера…
Собственици извън React
Когато състоянието принадлежи на услуга или на заявка към сървъра, създайте scope сами и извикайте destroy() накрая. Унищожаването на scope никога не изтрива запазени записи.
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(),
};
}