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.
How It Works
Section titled “How It Works”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"Usage Example
Section titled “Usage Example”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');  }}const { withUndoableState } = require('phaser-hooks');
class EditorScene extends Phaser.Scene {  create() {    const textState = withUndoableState(this, 'text', 'Initial text', 20);
    textState.on('change', (newValue) => {      console.log('Current text →', newValue);    });
    this.input.keyboard.on('keydown-Z', () => textState.undo());    this.input.keyboard.on('keydown-Y', () => textState.redo());
    textState.set('First change');    textState.set('Second change');  }}Internal Implementation
Section titled “Internal Implementation”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.
Usage Example
Section titled “Usage Example”const state = withUndoableState<T>(scene, key, initialValue, maxHistorySize);state.undo();  // ⏪ Move one step backstate.redo();  // ⏩ Move one step forwardstate.clearHistory(); // 🧹 Reset historyKey Features
Section titled “Key Features”| Feature | Description | 
|---|---|
| Undo / Redo | Navigate backward and forward through previous state values | 
| Automatic history | Every change is tracked without manual bookkeeping | 
| Custom history size | Control memory usage with maxHistorySize | 
| Scene-safe | Cleans up automatically when the scene is destroyed | 
| Type-safe | Works seamlessly with full TypeScript inference | 
When to Use
Section titled “When to Use”✅ 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