mutativejs/zustand-travel: Middleware undo/redo yang kuat dan berperforma tinggi untuk Zustand dengan Travels

 – Beragampengetahuan
6 mins read

mutativejs/zustand-travel: Middleware undo/redo yang kuat dan berperforma tinggi untuk Zustand dengan Travels – Beragampengetahuan

NodeCI
Manajemen proyek baru
lisensi

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

type State =
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
  1. fase inisialisasi:

    • menggunakan isInitializing Tandai untuk melewati perjalanan selama penyiapan
    • Panggil penginisialisasi untuk mendapatkan status awal melalui operasi
    • Pisahkan status data dari fungsi pengoperasian
  2. pemisahan negara:

    • Travels hanya melacak properti data
    • Fungsi tindakan disimpan secara terpisah
    • Hemat memori: tidak ada fungsi dalam riwayat
  3. 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
  4. Sinkronisasi dua arah:

    • Operasi pengguna → travelSettravels.setState
    • Perubahan perjalanan → penggabungan status + tindakan → Zustand (penggantian penuh)
  5. 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

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *