restate / v1.0.0
Lưu khi bạn quyết định
Giữ store trong IndexedDB hoặc MMKV, tải một lần khi khởi động, lưu tường minh hoặc tự động và hiển thị thay đổi chưa lưu.
Trên trang này
Khai báo store được lưuChờ một lần khi khởi độngLưu, hoàn tác và đặt lạiHiển thị thay đổi chưa lưu và tiến độThử ngayTự động lưuTrước khi đóng trangXử lý lỗi lưu trữKhai báo store được lưu
Thay restate bằng persistedRestate và đặt cho nó một key. Component vẫn dùng cùng hook và cùng set.
Giá trị đã lưu được tự động khôi phục sau khi tạo. Chỉnh sửa thay đổi bộ nhớ; không có gì được ghi cho đến khi bạn lưu hoặc bật autoSave.
import { persistedRestate } from '@kkwaenggwari/restate';
export const useDraft = persistedRestate('', {
key: 'article-draft',
validate: (value) => typeof value === 'string',
});Chờ một lần khi khởi động
Ở điểm vào phía client, import ứng dụng và các store của nó, rồi chờ restateManager.ready trước khi render. Từ đó component có thể đọc trực tiếp các giá trị đã lưu.
Bộ nhớ lưu trữ không khả dụng, như khi render phía máy chủ hoặc trong trình duyệt chặn nó, không phải lỗi: những store đó chạy trong bộ nhớ. ready chỉ bị từ chối khi bản ghi không thể đọc, di chuyển hoặc kiểm tra hợp lệ.
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();Lưu, hoàn tác và đặt lại
save ghi giá trị hiện tại, restore quay về giá trị đã lưu, còn resetAll xóa cả bộ nhớ lẫn bộ nhớ lưu trữ. Mỗi hàm trả về một Promise.
await useDraft.save(); // write the current value
await useDraft.restore(); // return to the saved value
await useDraft.resetAndClearStorage(); // initial value in memory, record removedHiển thị thay đổi chưa lưu và tiến độ
useStatus render lại khi trạng thái lưu thay đổi. dirty là true khi bộ nhớ khác với giá trị được tải, lưu hoặc khôi phục gần nhất. operation cho biết thao tác lưu trữ hiện tại.
Truyền selector để chỉ render lại khi một trường thay đổi.
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>}
</>
);
}Thử ngay
Gõ, tăng độ trễ lưu trữ rồi lưu. Phát lại ví dụ để thấy bản nháp được khôi phục.
Đang chuẩn bị ví dụ…
Tự động lưu
Bật một lần cho cài đặt và bản nháp luôn cần được lưu. autoSave: true lưu sau mỗi thay đổi; { delayMs } chờ đến khi thay đổi dừng lại.
Một loạt thay đổi trở thành một lần ghi, và quay về giá trị đã lưu thì không ghi gì. Lỗi xuất hiện trong status().error. Scope của component ghi thay đổi đang chờ khi unmount.
export const useTheme = persistedRestate('light', { key: 'theme', autoSave: true });
export const useDraft = persistedRestate('', {
key: 'article-draft',
autoSave: { delayMs: 500 },
});Trước khi đóng trang
Đọc cùng trạng thái đó bên ngoài React. Cảnh báo thay đổi chưa lưu trước khi rời trang, hoặc lưu tất cả khi trang bị ẩn.
window.addEventListener('beforeunload', (event) => {
if (useDraft.status().dirty) event.preventDefault();
});
window.addEventListener('pagehide', () => {
restateManager.saveAll();
});Xử lý lỗi lưu trữ
Lỗi lưu trữ làm Promise của thao tác bị từ chối. Mỗi lỗi restate có code, và với store được lưu còn có key của bản ghi.
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'}".`);
}