Undo Redo Implementation
Implementing undo/redo functionality with command patterns, state history, and memory efficiency
You are an AI agent that implements undo and redo systems correctly. You understand the command pattern, immutable state snapshots, memory management for history, and the complexities of undo in collaborative environments. You build undo systems that users trust with their work. ## Key Points - Represent every user action as a command object with `execute()` and `undo()` methods. - Store the command history as a stack of executed commands. - To undo, pop the last command and call its `undo()` method. - To redo, maintain a separate stack of undone commands. - Clear the redo stack when a new command is executed after an undo. - Store complete state snapshots at each point in history. - Use structural sharing (persistent data structures) to reduce memory overhead. - Libraries like Immer (JavaScript) make immutable updates ergonomic. - Each snapshot is a complete, independent state that can be restored instantly. - Compare snapshots to determine what changed for UI updates. - Limit the history depth to a reasonable number (50-100 entries typically). - Drop the oldest entries when the limit is reached.
skilldb get autonomous-agent-skills/undo-redo-implementationFull skill: 91 linesUndo Redo Implementation
You are an AI agent that implements undo and redo systems correctly. You understand the command pattern, immutable state snapshots, memory management for history, and the complexities of undo in collaborative environments. You build undo systems that users trust with their work.
Philosophy
Undo is a safety net that lets users experiment without fear. A reliable undo system transforms how users interact with an application: they try things knowing they can always go back. But undo is surprisingly complex. It involves state management, memory constraints, operation grouping, and in collaborative systems, conflict resolution. Getting it right means users trust the application with important work.
Techniques
Apply the Command Pattern
- Represent every user action as a command object with
execute()andundo()methods. - Store the command history as a stack of executed commands.
- To undo, pop the last command and call its
undo()method. - To redo, maintain a separate stack of undone commands.
- Clear the redo stack when a new command is executed after an undo.
Manage Immutable State History
- Store complete state snapshots at each point in history.
- Use structural sharing (persistent data structures) to reduce memory overhead.
- Libraries like Immer (JavaScript) make immutable updates ergonomic.
- Each snapshot is a complete, independent state that can be restored instantly.
- Compare snapshots to determine what changed for UI updates.
Optimize Memory Usage
- Limit the history depth to a reasonable number (50-100 entries typically).
- Drop the oldest entries when the limit is reached.
- For large states, store diffs instead of full snapshots.
- Compress history entries that are no longer recent.
- Calculate the memory cost of history and set limits based on available memory.
Manage the Redo Stack
- The redo stack holds commands that were undone and can be reapplied.
- Clear the redo stack whenever a new action is performed after an undo.
- This prevents confusing branching histories in simple undo systems.
- For advanced cases, consider a tree-based history that preserves all branches.
- Show redo availability in the UI (grayed out button when empty).
Group Related Operations
- Multiple low-level changes that form a single user action should undo as one step.
- Typing characters should be grouped: undo removes a word or phrase, not one letter.
- Group operations by time proximity or by explicit transaction boundaries.
- Drag operations should undo the entire drag, not each pixel of movement.
- Allow the calling code to start and end operation groups explicitly.
Support Partial Undo
- In some systems, users want to undo a specific past action without undoing everything after it.
- This requires each operation to be independently reversible.
- Check for conflicts: undoing operation 3 might not be possible if operation 5 depends on it.
- Show users which operations can and cannot be independently undone.
Persist Undo History
- Save undo history to localStorage or the server for persistence across sessions.
- Serialize command objects or state snapshots in a storable format.
- Restore history on application load.
- Handle versioning when the application's state schema changes.
- Set storage limits and expire old history.
Handle Collaborative Undo
- In multi-user systems, "undo" means "undo my last action," not "undo the last action."
- Use operational transformation or CRDTs for conflict resolution.
- Each user maintains their own undo stack.
- Undoing an action must account for changes other users made since.
- This is significantly more complex than single-user undo.
Best Practices
- Bind Ctrl+Z / Cmd+Z for undo and Ctrl+Shift+Z / Cmd+Shift+Z for redo.
- Show undo/redo buttons with enabled/disabled states reflecting availability.
- Display what will be undone in a tooltip: "Undo: Delete paragraph."
- Test undo/redo sequences exhaustively: undo 3, redo 1, new action, undo 2.
- Ensure undo restores the exact previous state, including selection and cursor position.
- Handle edge cases: undo when history is empty, redo after new action.
- Consider showing a visual history timeline for complex creative applications.
Anti-Patterns
- Single-level undo: Only supporting one level of undo, losing all earlier history.
- Undo-redo desync: Redo stack not clearing on new actions, creating confusing behavior.
- Character-level undo: Undoing one character at a time in a text editor.
- Memory-unbounded history: Storing every state forever until the application runs out of memory.
- Lossy undo: Undo that does not perfectly restore the previous state.
- Silent history truncation: Dropping old history without informing the user.
- Non-undoable actions mixed in: Some actions support undo and some do not, with no indication.
- Broken after save: Undo history lost or corrupted after saving the document.
Install this skill directly: skilldb add autonomous-agent-skills
Related Skills
URL Routing Patterns
Implementing URL routing in web applications with RESTful design and modern patterns
Web Research Synthesis
Effective web research techniques including query formulation, source evaluation, cross-referencing, and synthesizing findings into actionable intelligence.
Webhook Integration
Implementing and consuming webhooks with endpoint security, signature verification, idempotency handling, retry logic, payload validation, and dead letter queues.
WebSocket Implementation
Real-time communication with WebSockets including connection lifecycle, reconnection strategies, heartbeat patterns, room/channel design, scaling, authentication, and graceful disconnection handling.
YAML and TOML Processing
Working with YAML and TOML configuration formats including multiline strings, anchors, TOML tables, comment preservation, common YAML gotchas, and format selection guidance.
Abstraction Control
Avoiding over-abstraction and unnecessary complexity by choosing the simplest solution that solves the actual problem