Skip to content

Array Length Validator

The arrayLength validator ensures that an array has a specific length within a defined range.

validators.arrayLength(min: number, max?: number): StateValidator
  • min - Minimum allowed array length (inclusive)
  • max - Maximum allowed array length (inclusive, optional)
import { withLocalState, validators } from 'phaser-hooks';
export class GameScene extends Phaser.Scene {
create() {
// Inventory must have between 1 and 20 items
const inventory = withLocalState(this, 'inventory', [], {
validator: validators.arrayLength(1, 20)
});
// Player team must have exactly 4 members
const team = withLocalState(this, 'team', [], {
validator: validators.arrayLength(4, 4)
});
// Quest log must have at least 1 quest
const quests = withLocalState(this, 'quests', [], {
validator: validators.arrayLength(1)
});
}
}

Always wrap state updates in try/catch blocks when using validators:

const inventory = withLocalState(this, 'inventory', [], {
validator: validators.arrayLength(1, 20)
});
function addItem(item: any) {
try {
const currentItems = inventory.get();
const newItems = [...currentItems, item];
inventory.set(newItems);
console.log(`Added item. Inventory now has ${newItems.length} items`);
} catch (error) {
console.error('Invalid inventory size:', error.message);
// Handle the error - maybe remove oldest items
const currentItems = inventory.get();
if (currentItems.length >= 20) {
inventory.set(currentItems.slice(-19));
}
}
}
function removeItem(index: number) {
try {
const currentItems = inventory.get();
const newItems = currentItems.filter((_, i) => i !== index);
inventory.set(newItems);
} catch (error) {
console.error('Invalid inventory size:', error.message);
// Handle the error - maybe add a default item
inventory.set([{ id: 'default', name: 'Default Item' }]);
}
}
export class InventoryManager {
private items: HookState<any[]>;
private maxItems: number = 20;
constructor(scene: Phaser.Scene) {
this.items = withLocalState(scene, 'inventory', [], {
validator: validators.arrayLength(1, this.maxItems)
});
}
addItem(item: any) {
try {
const currentItems = this.items.get();
if (currentItems.length >= this.maxItems) {
throw new Error('Inventory is full');
}
const newItems = [...currentItems, item];
this.items.set(newItems);
return true;
} catch (error) {
console.error('Failed to add item:', error.message);
return false;
}
}
removeItem(itemId: string) {
try {
const currentItems = this.items.get();
const newItems = currentItems.filter(item => item.id !== itemId);
this.items.set(newItems);
return true;
} catch (error) {
console.error('Failed to remove item:', error.message);
// Ensure inventory has at least one item
this.items.set([{ id: 'default', name: 'Default Item' }]);
return false;
}
}
}
export class TeamManager {
private team: HookState<any[]>;
private teamSize: number = 4;
constructor(scene: Phaser.Scene) {
this.team = withLocalState(scene, 'team', [], {
validator: validators.arrayLength(this.teamSize, this.teamSize)
});
}
addMember(member: any) {
try {
const currentTeam = this.team.get();
if (currentTeam.length >= this.teamSize) {
throw new Error('Team is full');
}
const newTeam = [...currentTeam, member];
this.team.set(newTeam);
return true;
} catch (error) {
console.error('Failed to add team member:', error.message);
return false;
}
}
removeMember(memberId: string) {
try {
const currentTeam = this.team.get();
const newTeam = currentTeam.filter(member => member.id !== memberId);
this.team.set(newTeam);
return true;
} catch (error) {
console.error('Failed to remove team member:', error.message);
// Team must have exactly 4 members, so we can't remove
return false;
}
}
}
export class QuestManager {
private activeQuests: HookState<any[]>;
private maxQuests: number = 10;
constructor(scene: Phaser.Scene) {
this.activeQuests = withLocalState(scene, 'activeQuests', [], {
validator: validators.arrayLength(1, this.maxQuests)
});
}
addQuest(quest: any) {
try {
const currentQuests = this.activeQuests.get();
if (currentQuests.length >= this.maxQuests) {
throw new Error('Quest log is full');
}
const newQuests = [...currentQuests, quest];
this.activeQuests.set(newQuests);
return true;
} catch (error) {
console.error('Failed to add quest:', error.message);
return false;
}
}
completeQuest(questId: string) {
try {
const currentQuests = this.activeQuests.get();
const newQuests = currentQuests.filter(quest => quest.id !== questId);
this.activeQuests.set(newQuests);
return true;
} catch (error) {
console.error('Failed to complete quest:', error.message);
// Ensure at least one quest remains
this.activeQuests.set([{ id: 'default', name: 'Default Quest' }]);
return false;
}
}
}

The arrayLength validator returns specific error messages:

  • "Value must be an array" - When the value is not an array
  • "Array must have at least {min} items" - When the array is too short
  • "Array must have at most {max} items" - When the array is too long
  • If max is not provided, there’s no upper limit
  • The validator only checks array length, not array content
  • Empty arrays will fail if min is greater than 0