All questions

useUndoRedo

Premium

useUndoRedo

Undo/redo is a signature feature of any editor — a drawing app, a form builder, a text field. The canonical model is three stacks: past (everything you can undo back to), present (the current value), and future (everything you've undone and could redo). Every action shuffles values between them. useUndoRedo packages that model into a hook with undo, redo, set, reset, and the canUndo/canRedo flags that drive your toolbar buttons.

Implement useUndoRedo(initialPresent). Return { state, set, undo, redo, reset, canUndo, canRedo, past, future }. A set branches (clears the redo future); undo/redo move the present between the stacks; both are no-ops at the ends.

Signature

function useUndoRedo(initialPresent) {
  // returns { state, set, undo, redo, reset, canUndo, canRedo, past, future }
}

Examples

const { state, set, undo, redo, canUndo, canRedo } = useUndoRedo('');
set('hello'); set('hello world');
undo();  // state === 'hello'
redo();  // state === 'hello world'
set('a'); set('b'); undo(); // present 'a', future ['b']
set('c'); // branch: future cleared, canRedo === false

Notes

  • Three stackspast (undoable history), present (current), future (redoable). state is present.
  • set branches — push present to past, set the new value, and clear future (a fresh edit discards the redo path). No-op if unchanged.
  • undo / redo — move present to future and pop past (undo), or the reverse (redo); no-ops when the relevant stack is empty.
  • FlagscanUndo = past.length > 0, canRedo = future.length > 0. reset(next) clears both stacks. Keep the action callbacks stable.

Unlock the solution & editor

  • Runnable editor + tests

    Solve in the browser with instant Jest feedback.

  • Detailed solutions

    Walkthroughs, edge cases, and complexity notes.

  • Multi-framework variants

    React, Vue, Vanilla, Angular — same question, different stacks.

Upgrade to Premium