Skip to content

Your First Hook

Let’s create a simple counter using withLocalState:

Is a good practice create a hook as a function that returns a HookState object.

hooks/withCounter.ts
import { withLocalState } from 'phaser-hooks';
import * as Phaser from 'phaser';
export function withCounter(scene: Phaser.Scene) {
return withLocalState(scene, 'counter', 0);
}

Then you can use the hook in your scene like this:

scenes/GameScene.ts
import * as Phaser from 'phaser';
import { withCounter } from '../hooks/withCounter';
class GameScene extends Phaser.Scene {
create(): void {
const counter = withCounter(this);
const text = this.add.text(100, 100, 'Counter: ' + counter.get(), { fontSize: '20px', color: '#ffffff' });
counter.on('change', (value: number): void => {
text.setText('Counter: ' + value);
});
const { centerX, centerY } = this.cameras.main;
this.add.rectangle(centerX, centerY, 250, 50, 0x000000, 1)
.setInteractive({ useHandCursor: true })
.on('pointerdown', () => counter.set((current: number) => current + 1))
.setOrigin(0.5, 0.5);
this.add.text(centerX, centerY, 'Click to increment', { fontSize: '20px', color: '#ffffff' })
.setOrigin(0.5, 0.5);
}
}

Note: Notice how the state from the withCounter hook is reactive: by using the .on('change', ...) event, the displayed text is automatically updated whenever the counter value changes. This makes it easy to create dynamic behaviors and respond to state changes without needing manual UI update logic.

Try out the counter example in the interactive demo below:

Click to load the interactive demo