When building dynamic interfaces, especially where users can make changes (text editors, or design tools), providing undo and redo functionality dramatically improves user experience.
Thankfully, Vue + VueUse makes this a breeze with the useRefHistory
composable.
🔄 What is useRefHistory?
useRefHistory
from the @vueuse/core package allows you to track the history of changes to a ref in Vue. It enables you to programmatically undo or redo changes made to that ref, just like in text editors or drawing apps.
💡 Let's Build a Simple To-do App with Undo/Redo
In this example, we have a list of to-do items. Every time you add or remove an item, the change is tracked — and you can go back and forth using Undo and Redo buttons.
🧠 The Key Code:
import { ref } from "vue";
import { useRefHistory } from "@vueuse/core";
const todoItems = ref(["walk my dog", "go to the gym", "eat lunch"]);
const add = (e) => {
todoItems.push(e.target.value);
e.target.value = "";
};
const remove = (index) => todoItems.value.splice(index, 1);
// 👇 Track changes to `todoItems` and enable undo/redo
const { undo, redo } = useRefHistory(todoItems, {
deep: true,
});
Undo
Redo
{{ item }}
Remove
Here it is in action:
🛠 Use Cases for useRefHistory
Here are a few places where useRefHistory can be a game changer:
Forms: Revert user inputs step-by-step (e.g., a multi-field form with preview).
Design Tools: Let users undo shapes, colors, or movements in a canvas.
Text Editors: Implement undo/redo in markdown or WYSIWYG editors.
Games: Go back to previous states (e.g., board games like chess).
Collaborative Tools: Temporarily revert shared content locally before syncing changes.
📝 Final Thoughts
useRefHistory
is a simple yet powerful utility that adds professional polish to your Vue apps. Whether you're building productivity tools or just want to offer a better user experience, this is definitely one to have in your toolbox.
Want to see the full code? Try it yourself here!