javascript / expert
Snippet
Reactive State Snapshots for Undo/Redo
Implementing undo/redo logic requires taking point-in-time snapshots of reactive state. Using toRaw() is critical here to ensure you are capturing the underlying data without the proxy wrappers. Deep watching the state allows automatic tracking of any property change, while JSON serialization (or structured cloning) creates a true decoupled copy of the object for the history stack.
snippet.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { ref, watch, toRaw } from 'vue';const state = ref({ x: 0, y: 0 });const history = ref([]);watch(state, (newVal) => {// toRaw extracts the original object to avoid tracking history itselfif (history.value.length > 20) history.value.shift();history.value.push(JSON.parse(JSON.stringify(toRaw(newVal))));}, { deep: true });function undo() {if (history.value.length > 1) {history.value.pop(); // remove currentstate.value = history.value[history.value.length - 1];}}
vue
Breakdown
1
toRaw(newVal)
Returns the raw, non-reactive version of a Vue-created proxy object.
2
{ deep: true }
Ensures the watcher triggers even when nested properties of the state object are modified.