restate / v1.0.0
Guarda cuando tú decidas
Guarda un store en IndexedDB o MMKV, cárgalo una vez al arrancar, guarda de forma explícita o automática y muestra los cambios sin guardar.
En esta página
Declara un store guardadoEspera una vez al arrancarGuardar, revertir y restablecerMuestra los cambios sin guardar y el progresoPruébaloGuarda automáticamenteAntes de cerrar la páginaGestiona los errores de almacenamientoDeclara un store guardado
Sustituye restate por persistedRestate y dale una key. Los componentes siguen usando el mismo hook y el mismo set.
El valor guardado se restaura automáticamente tras la creación. Editar cambia la memoria; no se escribe nada hasta que guardes o actives autoSave.
import { persistedRestate } from '@kkwaenggwari/restate';
export const useDraft = persistedRestate('', {
key: 'article-draft',
validate: (value) => typeof value === 'string',
});Espera una vez al arrancar
En la entrada del cliente, importa la app y sus stores y espera a restateManager.ready antes de renderizar. Después, los componentes pueden leer directamente los valores guardados.
Que el almacenamiento no esté disponible, como durante el renderizado en servidor o en un navegador que lo bloquea, no es un fallo: esos stores funcionan en memoria. ready solo se rechaza cuando los registros no se pueden leer, migrar o validar.
import { createRoot } from 'react-dom/client';
import { restateManager } from '@kkwaenggwari/restate';
import App from './App';
async function start() {
const root = createRoot(document.getElementById('root'));
try {
await restateManager.ready;
root.render(<App />);
} catch (error) {
root.render(<p>Could not load saved data.</p>);
console.error(error);
}
}
start();Guardar, revertir y restablecer
save escribe el valor actual, restore vuelve al valor guardado y resetAll vacía tanto la memoria como el almacenamiento. Todos devuelven una Promise.
await useDraft.save(); // write the current value
await useDraft.restore(); // return to the saved value
await useDraft.resetAndClearStorage(); // initial value in memory, record removedMuestra los cambios sin guardar y el progreso
useStatus se vuelve a renderizar cuando cambia el estado de persistencia. dirty vale true mientras la memoria difiere del último valor cargado, guardado o restaurado. operation indica la operación de almacenamiento en curso.
Pasa un selector para volver a renderizar solo cuando cambie un campo.
function SaveButton() {
const { dirty, operation, error } = useDraft.useStatus();
const saving = operation === 'save';
return (
<>
<button disabled={!dirty || saving} onClick={() => useDraft.save().catch(() => {})}>
{saving ? 'Saving…' : 'Save'}
</button>
{error != null && <p>Could not save your draft.</p>}
</>
);
}Pruébalo
Escribe, sube la latencia del almacenamiento y guarda. Vuelve a reproducir el ejemplo para ver cómo se restaura el borrador guardado.
Preparando el ejemplo…
Guarda automáticamente
Para ajustes y borradores que siempre deben persistir, actívalo una vez. autoSave: true guarda tras cada cambio; { delayMs } espera a que los cambios se detengan.
Una ráfaga de cambios se convierte en una sola escritura, y volver al valor guardado no escribe nada. Los fallos aparecen en status().error. Un scope de un componente escribe el cambio pendiente al desmontarse.
export const useTheme = persistedRestate('light', { key: 'theme', autoSave: true });
export const useDraft = persistedRestate('', {
key: 'article-draft',
autoSave: { delayMs: 500 },
});Antes de cerrar la página
Lee el mismo estado fuera de React. Avisa antes de salir con cambios sin guardar, o guarda todo cuando la página se oculta.
window.addEventListener('beforeunload', (event) => {
if (useDraft.status().dirty) event.preventDefault();
});
window.addEventListener('pagehide', () => {
restateManager.saveAll();
});Gestiona los errores de almacenamiento
Los errores de almacenamiento rechazan la Promise de la operación. Todos los errores de restate tienen un code y, en los stores guardados, la key del registro.
try {
await useDraft.save();
} catch (error) {
if (error.code === 'STORAGE_UNAVAILABLE') showNotice('Saving is off in this browser.');
else if (error.code === 'STORAGE_VALUE_TOO_LARGE') showNotice('This draft is too large.');
else showNotice(`Could not save "${error.key ?? 'draft'}".`);
}