Hi, I’m new to XState and I have a question about working with class instances stored in a machine’s context.
According to the docs, it’s recommended to update context data via the assign(...) action.
But I’m building a card game using a class-based approach, and my context holds an instance of a Deck class.
Here’s a simplified example:
class Deck {
cards: string[]
constructor(cards: string[]) { this.cards = cards }
drawOne(): string { return this.cards.shift()! } // removes and returns the top card
}
import { createMachine, assign, createActor } from 'xstate'
const gameMachine = createMachine({
id: 'game',
initial: 'playing',
context: { deck: new Deck(['A♠','K♥','Q♦']), hand: [] as string[] },
states: {
playing: { on: { DRAW_CARD: { actions: 'drawCard' } } }
}
},{
actions: {
drawCard: assign({
hand: ({context}) => {
const card = context.deck.drawOne()
return [...context.hand, card]
}
})
}
})
const actor = createActor(gameMachine)
actor.start()
actor.subscribe(s => console.log('Deck:', s.context.deck.cards, ', Hand:', s.context.hand))
actor.send({type:'DRAW_CARD'})
actor.send({type:'DRAW_CARD'})
actor.send({type:'DRAW_CARD'})
// Output:
// Deck: [ 'K♥', 'Q♦' ] , Hand: [ 'A♠' ]
// Deck: [ 'Q♦' ] , Hand: [ 'A♠','K♥' ]
// Deck: [] , Hand: [ 'A♠','K♥','Q♦' ]
In this example, the deck instance is mutated directly inside an assign action, while hand is updated immutably.
My questions are:
- Is it acceptable in XState v5 to store mutable class instances in the context and call their methods that change internal state?
- Could this lead to unexpected behavior?
- Would you recommend always creating and returning new instances of Deck (and hand) inside assign, instead of mutating existing objects?
<@&826821237123842048>