restate / v1.0.0

何時儲存由你決定

把 store 存到 IndexedDB 或 MMKV,啟動時載入一次,明確或自動儲存,並顯示未儲存的修改。

本頁內容宣告持久化 store啟動時只等待一次儲存、復原與重設顯示未儲存的修改與進度動手試試自動儲存頁面關閉之前處理儲存錯誤

宣告持久化 store

把 restate 換成 persistedRestate 並給它一個 key。元件繼續使用同一個 Hook 與 set。

建立後會自動還原已儲存的值。編輯只會改變記憶體;在你儲存或開啟 autoSave 之前,不會寫入任何東西。

JavaScript / JSX
import { persistedRestate } from '@kkwaenggwari/restate';

export const useDraft = persistedRestate('', {
  key: 'article-draft',
  validate: (value) => typeof value === 'string',
});

啟動時只等待一次

在用戶端進入點匯入應用程式及其 store,然後在渲染前等待 restateManager.ready。之後元件就能直接讀取已儲存的值。

儲存空間無法使用(例如伺服器端渲染或瀏覽器封鎖了儲存空間)不算失敗:這些 store 會在記憶體中運作。只有在紀錄無法讀取、遷移或驗證時,ready 才會被拒絕。

JavaScript / JSX
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();

儲存、復原與重設

save 寫入目前的值,restore 回到已儲存的值,resetAll 會同時清除記憶體與儲存空間。它們都回傳 Promise。

JavaScript / JSX
await useDraft.save(); // write the current value
await useDraft.restore(); // return to the saved value
await useDraft.resetAndClearStorage(); // initial value in memory, record removed

顯示未儲存的修改與進度

持久化狀態改變時 useStatus 會重新渲染。當記憶體與上次載入、儲存或還原的值不同時,dirty 為 true。operation 表示正在執行的儲存操作。

傳入 selector,只在某個欄位改變時重新渲染。

JavaScript / JSX
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>}
    </>
  );
}

動手試試

輸入內容,調高儲存空間延遲後儲存。重新播放範例,就能看到已儲存的草稿被還原。

正在準備範例…

自動儲存

對於一律要儲存的設定與草稿,只要開啟一次。autoSave: true 會在每次變化後儲存;{ delayMs } 會等到變化停頓。

連續的變化會合併為一次寫入,改回已儲存的值則不會寫入。失敗會顯示在 status().error 中。元件擁有的 scope 會在卸載時寫入待處理的修改。

JavaScript / JSX
export const useTheme = persistedRestate('light', { key: 'theme', autoSave: true });

export const useDraft = persistedRestate('', {
  key: 'article-draft',
  autoSave: { delayMs: 500 },
});

頁面關閉之前

在 React 之外也能讀取同樣的狀態。有未儲存的修改時可以在離開前提醒,或在頁面隱藏時儲存全部內容。

JavaScript / JSX
window.addEventListener('beforeunload', (event) => {
  if (useDraft.status().dirty) event.preventDefault();
});

window.addEventListener('pagehide', () => {
  restateManager.saveAll();
});

處理儲存錯誤

儲存錯誤會讓該操作的 Promise 被拒絕。每個 restate 錯誤都有 code,持久化 store 的錯誤還會帶有紀錄的 key。

JavaScript / JSX
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'}".`);
}

搜尋文件

搜尋所有指南的標題、說明與內文。