Skip to content

Commit ab8fa3f

Browse files
committed
fix(core): skip afterTransition side effects during onInit hydrate replay
onInit replay reconstructs machine state by sending events through dispatch. Previously this also ran afterTransition which queued stale QueueFollowUp effects — silently swallowed because turn control handlers weren't bound yet. Now dispatch accepts a hydrate mode that skips afterTransition entirely during replay.
1 parent 5f4d578 commit ab8fa3f

1 file changed

Lines changed: 8 additions & 3 deletions

File tree

‎packages/core/src/runtime/extensions/spawn-machine-ref.ts‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,11 @@ export const spawnMachineExtensionRef = <
154154
),
155155
)
156156

157-
const dispatch = (machineEvent: Event, branchId: BranchId | undefined) =>
157+
const dispatch = (
158+
machineEvent: Event,
159+
branchId: BranchId | undefined,
160+
mode: "normal" | "hydrate" = "normal",
161+
) =>
158162
Effect.gen(function* () {
159163
const result = yield* machineRef
160164
.call(machineEvent)
@@ -185,7 +189,8 @@ export const spawnMachineExtensionRef = <
185189
),
186190
)
187191
}
188-
if (actor.afterTransition !== undefined) {
192+
// Skip side effects during hydrate — replay is state reconstruction only
193+
if (mode === "normal" && actor.afterTransition !== undefined) {
189194
const effects = actor.afterTransition(result.previousState, result.newState)
190195
if (effects.length > 0) {
191196
yield* runEffects(effects, branchId)
@@ -218,7 +223,7 @@ export const spawnMachineExtensionRef = <
218223
sessionId: ctx.sessionId,
219224
snapshot: machineRef.snapshot,
220225
send: (event) =>
221-
dispatch(event, ctx.branchId).pipe(
226+
dispatch(event, ctx.branchId, "hydrate").pipe(
222227
Effect.map((result) => result.transitioned),
223228
Effect.catchEager(() => Effect.succeed(false)),
224229
),

0 commit comments

Comments
 (0)