How do you implement an undo/redo system in React?
Answer
An undo/redo system requires storing a history of states. Using useReducer with a history stack: type HistoryState<T> = { past: T[]; present: T; future: T[] };. The reducer handles normal actions by pushing the current present to past, setting the new state as present, and clearing future. UNDO: pop from past, push present to future, set popped as present. REDO: pop from future, push present to past, set popped as present. Implement as a custom hook: function useHistory<T>(initialState: T) { const [state, dispatch] = useReducer(historyReducer, { past: [], present: initialState, future: [] }); const undo = () => dispatch({ type: "UNDO" }); const redo = () => dispatch({ type: "REDO" }); return { state: state.present, undo, redo, canUndo: state.past.length > 0, canRedo: state.future.length > 0 }; }. Optimizations: limit history length to prevent memory growth; use Immer for efficient state updates with structural sharing (unchanged parts of the state tree share references); debounce rapid changes (text input) to avoid storing every keystroke. Libraries like Redux Toolkit with redux-undo or Zustand with immer middleware handle this pattern well.
Previous
What are React rendering optimizations beyond React.memo?
Next
What are React's concurrent features and how do Transitions work?
More React.js Questions
View all →- Advanced How does React's reconciliation algorithm handle keys?
- Advanced What is the React Fiber architecture in depth?
- Advanced What are React rendering optimizations beyond React.memo?
- Advanced What are React's concurrent features and how do Transitions work?
- Advanced How does React handle forms at scale?