restate / v1.0.0
Un état propre à un composant
Donnez à chaque document, boîte de dialogue ou requête ses propres stores, créés avec le composant et libérés après son démontage.
Sur cette page
useRestateScopeRègles de la factoryValeurs initiales depuis les propsRendu serveurAttendre les données enregistrées d’un documentEssayerPropriétaires en dehors de ReactuseRestateScope
La factory déclare des stores et les renvoie. restate conserve le résultat d’un rendu à l’autre et détruit le scope après le démontage du composant. Aucune fonction de fermeture ni aucun effet de nettoyage à écrire.
Deux éléments Document ont des états indépendants. Pour partager un document avec ses enfants, transmettez les hooks renvoyés par les props ou par votre propre contexte.
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>
);
}Règles de la factory
React peut appeler la factory plusieurs fois et jeter les résultats : gardez-la synchrone et pure.
- Déclarez les stores dans la factory ; appelez les hooks renvoyés au niveau supérieur du composant.
- Les props initiales sont lues une seule fois, comme l’initialiseur de useState.
- Donnez une key au composant quand un autre document a besoin d’un état neuf.
- Sans factory, useRestateScope() renvoie un scope stable pour des stores que vous créerez plus tard, dans des effets ou des gestionnaires.
Valeurs initiales depuis les props
Utilisez les props comme valeurs initiales et une key React pour repartir de zéro avec un autre document.
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} />;Rendu serveur
Chargez les données dans votre route serveur et passez-les en prop. La valeur initiale fournit aussi le snapshot serveur. Dans l’App Router de Next.js, ce hook se place dans un Client Component, qui est lui aussi rendu côté serveur.
'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>;
}Attendre les données enregistrées d’un document
Les stores enregistrés d’un scope commencent leur restauration après la validation du composant côté client et ne font pas partie du restateManager.ready global. Attendez le manager.ready propre au scope dans une frontière de chargement.
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} />;
}Essayer
Ouvrez et fermez des documents et regardez leur état repartir de zéro.
Préparation de l’exemple…
Propriétaires en dehors de React
Quand un service ou une requête serveur possède l’état, créez le scope vous-même et appelez destroy() à la fin. Détruire un scope ne supprime jamais les enregistrements sauvegardés.
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(),
};
}