mutativejs/zustand-travel: Middleware undo/redo yang kuat dan berperforma tinggi untuk Zustand dengan Travels – Beragampengetahuan
Middleware undo/redo yang kuat dan berkinerja tinggi untuk Zustand dengan Travels.
- ✨ perjalanan waktu: Dukungan undo/redo penuh untuk toko Zustand
- 🎯 pembaruan mutasi:Menulis kode yang dapat diubah yang menghasilkan pembaruan yang tidak dapat diubah
- 📦 lampu: Dibangun pada penyimpanan JSON Patch yang efisien
- ⚡ kinerja tinggi: Didukung oleh Mutative (10x lebih cepat dari Immer)
- 🔧 Dapat dikonfigurasi: Ukuran catatan riwayat dan mode arsip yang dapat disesuaikan
- 🔄 kontrol respons:Akses kontrol perjalanan waktu kapan saja, di mana saja
npm install zustand-travel travels mutative zustand
# or
yarn add zustand-travel travels mutative zustand
# or
pnpm add zustand-travel travels mutative zustand
import create from 'zustand';
import travel from 'zustand-travel';
type State =
count: number;
;
type Actions =
increment: (qty: number) => void;
decrement: (qty: number) => void;
;
export const useCountStore = create<State & Actions>()(
travel((set) => (
count: 0,
increment: (qty: number) =>
set((state) =>
state.count += qty; // ⭐ Mutation style for efficient JSON Patches
),
decrement: (qty: number) =>
set((state) =>
state.count -= qty; // ⭐ Recommended approach
),
))
);
// Access controls
const controls = useCountStore.getControls();
controls.back(); // Undo
controls.forward(); // Redo
controls.reset(); // Reset to initial state
travel(initializer, options?)
| Pilihan | jenis | bawaan | menggambarkan |
|---|---|---|---|
maxHistory |
nomor | 10 | Jumlah maksimum entri riwayat dipertahankan |
autoArchive |
Nilai Boolean | nyata | Mengarsipkan perubahan secara otomatis (lihat Mode Arsip) |
initialPosition |
nomor | 0 | posisi awal dalam sejarah |
initialPatches |
tempelan perjalanan | – | Patch awal yang persisten |
Mengembalikan objek kontrol dengan metode perjalanan waktu:
const controls = useStore.getControls();
controls.back(amount?: number) // Go back in history
controls.forward(amount?: number) // Go forward in history
controls.go(position: number) // Go to specific position
controls.reset() // Reset to initial state
controls.canBack(): boolean // Check if can go back
controls.canForward(): boolean // Check if can go forward
controls.getHistory(): State[] // Get full history
controls.position: number // Current position
controls.patches: TravelPatches // Current patches
Mode arsip manual (Kapan autoArchive: false):
// you can use type `StoreApi`, e.g. `controls as Controls<StoreApi< count: number; >,false>`
controls.archive() // Archive current changes
controls.canArchive(): boolean // Check if can archive
Middleware mendukung tiga cara untuk memperbarui status:
set((state) =>
state.count += 1;
state.nested.value = 'new';
);
set(() => ( count: 10 ));
Gunakan gaya mutasi (set(fn)) untuk sebagian besar pembaruan status Manfaatkan sepenuhnya mekanisme JSON Patch Mutative:
// ✅ Recommended: Efficient JSON Patches
set((state) =>
state.count += 1;
state.user.name = 'Alice';
);
Hanya gunakan nilai langsung (set(value)) untuk kasus khusus:
- Memulihkan keadaan dari kegigihan
- Tetapkan nilai awal
- Penggantian status penyelesaian
// ✅ Good use case: Restoring from persistence
const loadFromStorage = () =>
const savedState = JSON.parse(localStorage.getItem('state'));
set(savedState, true); // Replace entire state
;
Mengapa mutasi lebih efektif:
Saat Anda menggunakan gaya mutasi, Mutative secara akurat melacak properti yang diubah dan menghasilkan patch JSON minimal. Misalnya:
// Only generates a patch for the changed property
set((state) =>
// ✅ Efficient: Only tracks the changed property
state.count = 5; // Patch: [ op: 'replace', path: 'count', value: 5 ]
);
Sebaliknya, pembaruan nilai langsung dikonversi secara internal untuk mencatat patch objek, bukan patch ringkas:
// ❌ Inefficient: Records the entire object as a patch
set( count: 5 ); // Internally: record ` count: 5 ` as a patch
Manfaat patching yang efisien:
- Jejak memori yang lebih kecil: Riwayat hanya menyimpan properti yang diubah
- Membatalkan/mengulang lebih cepat: Menerapkan tambalan kecil lebih cepat daripada mengganti seluruh objek
- kinerja yang lebih baik: Terutama penting untuk negara-negara yang kompleks dan sangat tersarang
- Pelacakan yang akurat:Hanya mencatat perubahan aktual
setiap set Panggilan untuk membuat entri riwayat baru:
const useStore = create<State>()(
travel((set) => (
count: 0,
increment: () =>
set((state) =>
state.count += 1;
),
))
);
// Each call creates a history entry
increment(); // History: [0, 1]
increment(); // History: [0, 1, 2]
Kelompokkan beberapa perubahan menjadi satu langkah undo/redo:
const useStore = create<State>()(
travel(
(set) => (
count: 0,
increment: () =>
set((state) =>
state.count += 1;
),
save: () =>
const controls = useStore.getControls();
if ('archive' in controls)
controls.archive();
,
),
autoArchive: false
)
);
increment(); // Temporary change
increment(); // Temporary change
save(); // Archive as single entry
Keadaan kompleks dengan pembaruan bersarang
todos: Todo[];
;
type Actions =
addTodo: (text: string) => void;
toggleTodo: (id: number) => void;
removeTodo: (id: number) => void;
;
const useTodoStore = create<State & Actions>()(
travel((set) => (
todos: [],
addTodo: (text) =>
set((state) =>
state.todos.push(
id: Date.now(),
text,
done: false,
);
),
toggleTodo: (id) =>
set((state) =>
const todo = state.todos.find((t) => t.id === id);
if (todo)
todo.done = !todo.done;
),
removeTodo: (id) =>
set((state) =>
state.todos = state.todos.filter((t) => t.id !== id);
),
))
);
function TodoApp()
const todos, addTodo, toggleTodo = useTodoStore();
const controls = useTodoStore.getControls();
return (
<div>
<TodoList todos=todos onToggle=toggleTodo />
<div className="controls">
<button
onClick=() => controls.back()
disabled=!controls.canBack()
>
Undo
</button>
<button
onClick=() => controls.forward()
disabled=!controls.canForward()
>
Redo
</button>
<button onClick=() => controls.reset()>
Reset
</button>
</div>
<div>
Position: controls.position / controls.patches.patches.length
</div>
</div>
);
Persistence adalah kasus penggunaan yang sempurna untuk inisialisasi nilai langsung karena Anda ingin memulihkan keadaan secara lengkap:
// Save state for persistence
const saveToStorage = () =>
const controls = useStore.getControls();
const state = useStore.getState();
localStorage.setItem('state', JSON.stringify(state));
localStorage.setItem('patches', JSON.stringify(controls.patches));
localStorage.setItem('position', JSON.stringify(controls.position));
;
// Load state on initialization
const loadFromStorage = () => '0');
return state, patches, position ;
;
const state, patches, position = loadFromStorage();
// ✅ Direct value initialization is appropriate here
// We're setting the complete initial state from storage
const useStore = create<State>()(
travel(() => state,
initialPatches: patches,
initialPosition: position,
)
);
catatan: Fungsi inisialisasi () => state Dipanggil saat pengaturan isInitializing bendera disetel ke truesehingga melewati pelacakan perjalanan. Ini adalah cara yang benar untuk mengatur keadaan awal dari persistensi.
Dukungan penuh TypeScript dengan inferensi tipe:
import create from 'zustand';
import travel from 'zustand-travel';
type State =
count: number;
user: name: string; age: number ;
;
type Actions =
updateUser: (updates: Partial<State['user']>) => void;
;
const useStore = create<State & Actions>()(
travel((set) => (
count: 0,
user: name: 'Alice', age: 30 ,
updateUser: (updates) =>
set((state) =>
Object.assign(state.user, updates);
),
))
);
// Full type safety
const controls = useStore.getControls(); // Typed controls
const history = controls.getHistory(); // State[] with full types
-
fase inisialisasi:
- menggunakan
isInitializingTandai untuk melewati perjalanan selama penyiapan - Panggil penginisialisasi untuk mendapatkan status awal melalui operasi
- Pisahkan status data dari fungsi pengoperasian
- menggunakan
-
pemisahan negara:
- Travels hanya melacak properti data
- Fungsi tindakan disimpan secara terpisah
- Hemat memori: tidak ada fungsi dalam riwayat
-
Penanganan pembaru yang cerdas:
- Fungsi: diteruskan langsung ke trip (secara otomatis mendeteksi mutasi/pengembalian)
- nilai dengan penggantian: Penggantian langsung
- Pembaruan sebagian:Konversi ke mutasi
Object.assign
-
Sinkronisasi dua arah:
- Operasi pengguna →
travelSet→travels.setState - Perubahan perjalanan → penggabungan status + tindakan → Zustand (penggantian penuh)
- Operasi pengguna →
-
simpan tindakan:
- Operasi mempertahankan referensi stabil selama pembatalan/pengulangan
- Selalu gabungkan dengan pembaruan status
- penyimpanan yang efisien: Gunakan patch JSON alih-alih snapshot status penuh
- pembaruan cepat: Didukung oleh Mutative (10x lebih cepat dari Immer)
- overhead minimal:Hanya melacak perubahan data, bukan fungsi
- Perjalanan – Inti pembatalan/pengulangan kerangka-agnostik
- mutatif – Pembaruan yang efisien dan tidak dapat diubah
- zustand – menanggung keperluan penyelenggaraan negara
MIT
rencana pengembangan website
metode pengembangan website
jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website
#mutativejszustandtravel #Middleware #undoredo #yang #kuat #dan #berperforma #tinggi #untuk #Zustand #dengan #Travels