DEV Community

Obiwan Pelosi
Obiwan Pelosi

Posted on

✨ Vue Tip: Add Undo/Redo to Your App with useRefHistory

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.

Project UI

🧠 The Key Code:

<script setup>
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,
});
</script>
<template>
  <div>
    <button @click="undo">Undo</button>
    <button @click="redo">Redo</button>

    <input type="text" @keyup.enter="add" placeholder="Add todo" />
    <ul>
      <li v-for="(item, index) in todoItems" :key="item">
        {{ item }}
        <button @click="remove(index)">Remove</button>
      </li>
    </ul>
  </div>
</template>


Enter fullscreen mode Exit fullscreen mode

Here it is in action:

image showing ref history 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!

Top comments (2)

Collapse
 
nevodavid profile image
Nevo David

Amazing explanation and very easy to understand! How could this feature be expanded to support larger state changes efficiently?

Collapse
 
obiwanpelosi profile image
Obiwan Pelosi

It works quite well for even larger state changes, and you can even define your own clone function that goes past x => JSON.parse(JSON.stringify(x)) which is what useRefHistory uses by default. Check the docs here