Skip to content

useUndoRedo โ€‹

A React hook to manage state history with undo and redo functionality.
It maintains past, present, and future states, allowing you to easily roll back or redo changes โ€” ideal for text editors, drawing apps, and complex forms.


๐Ÿ“ฆ Import โ€‹

ts
import { useUndoRedo } from "react-hookstack";

๐Ÿง  Quick Example โ€‹

tsx
const { present, set, undo, redo } = useUndoRedo<number>(0);

set(1); // present = 1
undo(); // present = 0
redo(); // present = 1

๐Ÿงฉ API Reference โ€‹

Parameters โ€‹

ParameterTypeDefaultDescription
initialTโ€”The initial state value.

Returns โ€‹

PropertyTypeDescription
pastT[]An array of all previous states.
presentTThe current active state.
futureT[]An array of undone states that can be redone.
set(newPresent: T) => voidUpdates the state and resets the future history.
undo() => voidMoves one step back in history.
redo() => voidMoves one step forward in history.

๐Ÿงช Use Cases โ€‹

  • โœ๏ธ Text or code editors
  • ๐ŸŽจ Drawing and design tools
  • ๐Ÿงพ Form history navigation
  • ๐Ÿ”„ Versioned state management

๐Ÿ—’๏ธ Notes โ€‹

  • Calling set clears the future (redo history) โ€” mimicking real-world editors.
  • Each change is stored immutably, so previous states remain intact.
  • Undo/redo depth depends on your appโ€™s needs (can be extended easily).

โš™๏ธ Implementation โ€‹

tsx
import { useState, useCallback } from "react";

export function useUndoRedo<T>(initial: T) {
  const [past, setPast] = useState<T[]>([]);
  const [present, setPresent] = useState<T>(initial);
  const [future, setFuture] = useState<T[]>([]);

  const set = useCallback(
    (newPresent: T) => {
      setPast((p) => [...p, present]);
      setPresent(newPresent);
      setFuture([]);
    },
    [present]
  );

  const undo = useCallback(() => {
    setPast((p) => {
      if (p.length === 0) return p;
      setFuture((f) => [present, ...f]);
      setPresent(p[p.length - 1]);
      return p.slice(0, -1);
    });
  }, [present]);

  const redo = useCallback(() => {
    setFuture((f) => {
      if (f.length === 0) return f;
      setPast((p) => [...p, present]);
      setPresent(f[0]);
      return f.slice(1);
    });
  }, [present]);

  return { past, present, future, set, undo, redo };
}

๐Ÿงฐ Type Definition โ€‹

tsx
export function useUndoRedo<T>(
  initial: T
): {
  past: T[];
  present: T;
  future: T[];
  set: (newPresent: T) => void;
  undo: () => void;
  redo: () => void;
};