Enable Dark Mode!
how-to-build-an-undo-redo-feature-in-react.jpg
By: Alan Joy

How to Build an Undo/Redo Feature in React

Technical React

Most of us may have faced this situation, where we have made a change in an application and wished to go back to a previous version. Undo and redo features add this function to our application. They help users to go back to a previous version and restore the changes they made. We can find this feature in many applications like text editors, drawing tools, document editors, etc. The main idea behind the undo and redo buttons is to store the previous states and use them to undo or redo the data. In this blog, we will build a simple undo and redo feature with React and useState.

1. Create a React Project

First, we can create a React project. Use this command to create a React project with Vite.

npm create vite@latest react-undo-redo -- --template react
cd react-undo-redo
npm install
npm run dev

2. How Undo and Redo Work

Before developing our react component, let's understand how undo and redo work and their basic concepts. For an undo and redo function to work, we need to store the different versions of our application state. Mainly, we need three state values for this: past, present, and future. Past stores the previous state, present stores the current state, and future stores the states that can be restored.

3. Create the Editor Component

First, we can create the editor component. Create a new file named UndoRedo.jsx and add this code. This will create a simple text editor.

import { useState } from "react";
export default function UndoRedo() {
 const [text, setText] = useState("");
 return (
   <div>
     <textarea
       value={text}
       onChange={(event) => setText(event.target.value)}
       placeholder="Start typing..."
     />
   </div>
 );
}

4. Store the State History

Now, we can set up the states for undo and redo options. Update the component with this code.

const [history, setHistory] = useState({
 past: [],
 present: "",
 future: [],
});

Now, add the function to handle this state.

const handleChange = (event) => {
 const newText = event.target.value;
 setHistory((current) => ({
   past: [...current.past, current.present],
   present: newText,
   future: [],
 }));
};

Update the textarea to connect the function.

<textarea
 value={history.present}
 onChange={handleChange}
 placeholder="Start typing..."
/>

5. Implement the Undo Function

Now, we can set up the undo function. In an undo function, we need to take the latest past value and set it as the current value. Added this function to the component.

const undo = () => {
 setHistory((current) => {
   if (current.past.length === 0) {
     return current;
   }
   const previous = current.past[current.past.length - 1];
   return {
     past: current.past.slice(0, -1),
     present: previous,
     future: [current.present, ...current.future],
   };
 });
};

6. Implement the Redo Function

Next, we can create the redo function. Redo is the opposite of undo; we need to take the first value in the future state and set it in the current state. Add this function to the component.

const redo = () => {
 setHistory((current) => {
   if (current.future.length === 0) {
     return current;
   }
   const next = current.future[0];
   return {
     past: [...current.past, current.present],
     present: next,
     future: current.future.slice(1),
   };
 });
};

7. Add Undo and Redo Buttons

We have already added the functions for the undo and redo buttons. Now, we can add the buttons for them. Add this code to the component.

<div>
 <button
   onClick={undo}
   disabled={history.past.length === 0}
 >
   Undo
 </button>
 <button
   onClick={redo}
   disabled={history.future.length === 0}
 >
   Redo
 </button>
</div>

8. Complete Undo/Redo Component

import { useState } from "react";
export default function UndoRedo() {
 const [history, setHistory] = useState({
   past: [],
   present: "",
   future: [],
 });
 const handleChange = (event) => {
   const newText = event.target.value;
   setHistory((current) => ({
     past: [...current.past, current.present],
     present: newText,
     future: [],
   }));
 };
 const undo = () => {
   setHistory((current) => {
     if (current.past.length === 0) {
       return current;
     }
     const previous = current.past[current.past.length - 1];
     return {
       past: current.past.slice(0, -1),
       present: previous,
       future: [current.present, ...current.future],
     };
   });
 };
 const redo = () => {
   setHistory((current) => {
     if (current.future.length === 0) {
       return current;
     }
     const next = current.future[0];
     return {
       past: [...current.past, current.present],
       present: next,
       future: current.future.slice(1),
     };
   });
 };
 return (
   <div className="mx-auto max-w-lg rounded-lg border p-6">
     <h2 className="mb-4 text-lg font-semibold">
       Simple Text Editor
     </h2>
     <textarea
       value={history.present}
       onChange={handleChange}
       placeholder="Start typing..."
       className="mb-4 h-40 w-full rounded-md border p-3"
     />
     <div className="flex gap-3">
       <button
         onClick={undo}
         disabled={history.past.length === 0}
         className="rounded bg-blue-600 px-4 py-2 text-white disabled:opacity-50"
       >
         Undo
       </button>
       <button
         onClick={redo}
         disabled={history.future.length === 0}
         className="rounded bg-blue-600 px-4 py-2 text-white disabled:opacity-50"
       >
         Redo
       </button>
     </div>
   </div>
 );
}

Import our component into the App.jsx file to use it.

import UndoRedo from "./UndoRedo";
function App() {
 return (
   <div className="p-6">
     <UndoRedo />
   </div>
 );
}
export default App;

Building undo and redo functions in a React application can become very easier when we understand the working of react states. By providing undo and redo buttons to our applications, it will be very useful for users to handle previous changes. It is a good practice to provide undo and redo functions for a text editor, document editor, and other applications.

To read more about How to Create an Image Preview Component in React, refer to our blog How to Create an Image Preview Component in React.


Frequently Asked Questions

How do undo and redo work in React?

Undo and redo work by storing previous and future versions of the application state. Undo restores an earlier state, while redo restores a state that was previously undone.

What are past, present, and future in undo/redo?

Past stores previous states, present stores the current state, and future stores states that can be restored using redo.

Should I use useState or useReducer for undo/redo?

Both can be used. useState works well for simple examples, while useReducer can make more complex history management easier to organize.

If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



WhatsApp