8
Hooks

useUndoRedo

A hook for managing state history with undo and redo functionality.

useUndoRedo

The useUndoRedo hook provides a convenient way to add undo and redo functionality to any state in your React application. It maintains a history of state changes, allowing users to easily navigate back and forth through previous states.

Text Editor
0 changes

Installation

Install the useUndoRedo hook using:

npx axionjs-ui add hook use-undo-redo

File Structure

use-undo-redo.ts

Parameters

PropTypeDefault
initialPresent
T
Required

Return Value

PropTypeDefault
state
T
-
set
(newPresent: T) => void
-
undo
() => void
-
redo
() => void
-
clear
() => void
-
canUndo
boolean
-
canRedo
boolean
-
history
HistoryState<T>
-

Examples

Color Picker with History

A simple color picker that maintains a history of color selections.

Color Picker with History
No changes

Advanced Task Manager

A more complex example showing how to use useUndoRedo with an array of objects.

Task Manager
Learn React
Build a project
Deploy to production

Using with Form State

The useUndoRedo hook can be particularly useful for forms where you want to track changes and allow users to undo or redo their edits.

import { useUndoRedo } from "@/hooks/use-undo-redo";
 
interface FormData {
  name: string;
  email: string;
  message: string;
}
 
function ContactForm() {
  const initialFormData: FormData = {
    name: "",
    email: "",
    message: ""
  };
  
  const { state, set, undo, redo, canUndo, canRedo, clear } = useUndoRedo<FormData>(initialFormData);
  
  const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
    const { name, value } = e.target;
    set({
      ...state,
      [name]: value
    });
  };
  
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    // Submit form data...
    alert(`Form submitted with: ${JSON.stringify(state)}`);
    clear(); // Reset form and history after submission
  };
  
  const handleReset = () => {
    clear(); // Reset to initial state and clear history
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="name">Name</label>
        <input
          id="name"
          name="name"
          value={state.name}
          onChange={handleChange}
        />
      </div>
      
      <div>
        <label htmlFor="email">Email</label>
        <input
          id="email"
          name="email"
          type="email"
          value={state.email}
          onChange={handleChange}
        />
      </div>
      
      <div>
        <label htmlFor="message">Message</label>
        <textarea
          id="message"
          name="message"
          value={state.message}
          onChange={handleChange}
        />
      </div>
      
      <div>
        <button type="button" onClick={undo} disabled={!canUndo}>Undo</button>
        <button type="button" onClick={redo} disabled={!canRedo}>Redo</button>
        <button type="button" onClick={handleReset}>Reset</button>
        <button type="submit">Submit</button>
      </div>
    </form>
  );
}

Use Cases

  • Content Editors: Text editors, rich text editors, code editors
  • Form Management: Track changes and allow users to revert to previous inputs
  • Drawing Applications: Maintain a history of canvas states
  • Game Development: Implement undo/redo in game logic
  • Configuration Interfaces: Track changes to settings or configurations
  • Data Entry Systems: Allow users to correct mistakes easily
  • Interactive Tutorials: Guide users through steps with ability to go back

Accessibility

To ensure accessible implementation:

  • Clearly communicate to users when undo/redo actions are available
  • Provide keyboard shortcuts (e.g., Ctrl+Z, Ctrl+Y) for undo and redo
  • Include appropriate ARIA attributes for buttons and controls
  • Ensure focus management when performing undo/redo operations

Best Practices

  • Performance Considerations: Be mindful of memory usage when storing large objects in history
  • Deep Cloning: Make sure to properly clone complex objects to avoid reference issues
  • Debouncing: Consider debouncing rapid state changes before adding them to history
  • Maximum History Size: Implement a maximum history size to prevent memory issues
  • Batch Operations: Group related changes into a single history entry when appropriate

On this page