Skip to content

Best Practices

Guidelines for writing maintainable custom hooks.

// ✅ Single responsibility
export function withPlayer(scene) { ... }
export function withInventory(scene) { ... }
// ❌ Too much in one hook
export function withEverything(scene) {
// Player, inventory, quests, enemies, UI...
}
// ✅ Type-safe
type PlayerState = HookState<Player> & {
takeDamage: (amount: number) => void;
};
export function withPlayer(scene: Phaser.Scene): PlayerState { ... }
// ✅ Sensible defaults
export function withPlayer(scene: Phaser.Scene) {
return withLocalState(scene, 'player', {
hp: 100, // Default
maxHp: 100,
level: 1
});
}
// ✅ Consistent convention
withPlayer
withEnemy
withInventory
withSettings
// ❌ Exposes implementation
export function withPlayer(scene) {
const state = withLocalState(...);
return { state, doSomething: () => {} }; // Don't return raw state
}
// ✅ Only expose API
export function withPlayer(scene) {
const state = withLocalState(...);
return { ...state, doSomething: () => {} };
}
// ❌ Circular
export function withPlayer(scene) {
const inventory = withInventory(scene);
// Uses inventory...
}
export function withInventory(scene) {
const player = withPlayer(scene); // ❌ Circular!
// Uses player...
}
// ✅ Use composition instead
export function withGame(scene) {
const player = withPlayer(scene);
const inventory = withInventory(scene);
return { player, inventory };
}
// ❌ Hook knows too much about scene
export function withPlayer(scene) {
const state = withLocalState(...);
return {
...state,
die: () => {
scene.scene.start('GameOverScene'); // ❌ Hook shouldn't control scenes
}
};
}
// ✅ Let scene handle navigation
export function withPlayer(scene) {
const state = withLocalState(...);
return {
...state,
die: () => {
state.set({ hp: 0, isAlive: false });
scene.events.emit('player-died'); // ✅ Emit event instead
}
};
}
// In scene:
player.on('change', (p) => {
if (!p.isAlive) {
this.scene.start('GameOverScene');
}
});
  • One hook = one concern
  • Methods should be pure when possible
  • Use events for side effects
  • Keep hooks testable
  • Document complex logic