BACK
Use casesUndo/redo — история изменений формы
Use cases · 14

Undo/redo — история изменений формы

Паттерн

Редактор, конструктор, сложная форма. Пользователь должен иметь возможность откатить изменение (Ctrl+Z) и вернуть его обратно (Ctrl+Y). Модель: три списка — past, present, future.

Какую проблему решаем

Если хранить историю в массивах и мутировать их из обработчиков кнопок — рано или поздно past и future рассинхронизируются. Особенно после нового edit поверх старого undo: классическая ошибка — забыть очистить future, и redo применит «призрак» из удалённой ветки истории.

Операторы и зачем они нужны

  • Subject — принимает команды: edit, undo, redo, snapshot.
  • scan — это и есть наш reducer. Он держит {past, present, future} и применяет команды как чистая функция.
  • map — выделяет present для шаблона.
  • withLatestFrom — нужен для snapshot: «возьми текущее present в момент команды save».

Подводные камни

  • После нового edit обязательно чистить future. Иначе redo вернёт состояние из удалённой ветки истории.
  • Reducer должен быть чистым (никаких мутаций массивов in-place). Иначе OnPush change detection пропустит обновление.
  • BehaviorSubject с ручными next тоже работает, но scan-reducer чище тестируется через marble-тесты.

Что в итоге получаем

История превращается в предсказуемую state machine без императивных флагов. Логика undo/redo описана одной чистой функцией.

script.ts // TypeScript
CONSOLE · Console Output
Нажмите на запуск, чтобы увидеть результат...