Skip to content

With Undoable State

The withUndoableState hook provides state management with undo and redo history, similar to how text editors or design tools work.
It extends a regular HookState with methods like undo(), redo(), and clearHistory() — making it perfect for editors, level designers, or sandbox tools where the user needs to revert or reapply changes.


withUndoableState internally tracks every change made to the state, storing snapshots in a history list.
When you call set() or patch(), it pushes the new value to history.
You can then move backward or forward using undo() and redo().

Each history entry is capped by a maxHistorySize parameter to prevent unbounded memory usage.

const text = withUndoableState<string>(scene, 'text', 'Hello world', 10);
text.set('Hello Phaser');
text.set('Hello Phaser Hooks');
text.undo(); // 🔙 Restores "Hello Phaser"
text.redo(); // 🔁 Returns to "Hello Phaser Hooks"
import { withUndoableState } from 'phaser-hooks';
class EditorScene extends Phaser.Scene {
create() {
const textState = withUndoableState<string>(
this,
'text',
'Initial text',
20 // keep 20 history steps
);
textState.on('change', (newValue) => {
console.log('Current text →', newValue);
});
// Example bindings
this.input.keyboard.on('keydown-Z', () => {
if (this.input.keyboard.checkDown(this.input.keyboard.addKey('Z'), 250)) {
textState.undo();
}
});
this.input.keyboard.on('keydown-Y', () => {
textState.redo();
});
// Simulate edits
textState.set('First change');
textState.set('Second change');
}
}

Under the hood, this hook creates three internal states:

  • currentState → Holds the active value
  • historyState → Array of all past values
  • historyIndexState → Keeps track of the current position in the history

Every time set() or patch() is called, the new value is pushed into the history array and the index moves forward. Undo and redo simply adjust that index and restore the corresponding value.

const state = withUndoableState<T>(scene, key, initialValue, maxHistorySize);
state.undo(); // ⏪ Move one step back
state.redo(); // ⏩ Move one step forward
state.clearHistory(); // 🧹 Reset history
FeatureDescription
Undo / RedoNavigate backward and forward through previous state values
Automatic historyEvery change is tracked without manual bookkeeping
Custom history sizeControl memory usage with maxHistorySize
Scene-safeCleans up automatically when the scene is destroyed
Type-safeWorks seamlessly with full TypeScript inference

Use withUndoableState for:

  • Level editors or tile map editors
  • UI builders or design tools
  • Text input or scripting systems
  • Sandbox-style games where the player edits things

Don’t use withUndoableState for:

  • Fast-moving data like physics or animations
  • High-frequency values (hundreds of updates per second)
  • Temporary state that doesn’t need rollback