Snapshot and Delta Events
Client state depends on a deliberate snapshot-and-delta pattern:
hydratereturns the initial state during audition.- Later handlers emit delta events such as
MoveMadeorGameEnded. - Client reducers fold deltas into the hydrated state.
Without hydration, a reconnecting UI usually needs a separate imperative fetch path.
Hydrate on connect
export const hydrate = Effect.gen(function* () {
const room = yield* loadRoom
return {
roomId: room.id,
members: room.members,
messages: room.messages,
}
})Delta from handlers
export const sendMessage = RoomActor.handler(
"SendMessage",
Effect.fn(function* ({ content }) {
const message = yield* saveMessage(content)
yield* RoomActor.all.send("MessageAdded", {
message,
})
}),
)Reduce locally
export const MessageAdded = RoomClient.reducer(
"MessageAdded",
({ message }) =>
(state) =>
Effect.succeed({
...state,
messages: [...state.messages, message],
}),
)This keeps the client state model hydrated before the UI sees it and event-driven afterward.
Read Lifecycle for hydrate and Client State for the reduction loop.