Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/next' into v5/sta-3440-remove-au…
Browse files Browse the repository at this point in the history
…toforward

# Conflicts:
#	packages/core/test/invoke.test.ts
  • Loading branch information
Andarist committed Mar 24, 2023
2 parents c21e2eb + 9e18af1 commit 234d416
Show file tree
Hide file tree
Showing 24 changed files with 221 additions and 311 deletions.
13 changes: 13 additions & 0 deletions .changeset/lemon-dancers-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'xstate': major
---

The `actor.onTransition(...)` method has been removed in favor of `.subscribe(...)`

```diff
const actor = interpret(machine)
- .onTransition(...)
- .start();
+actor.subscribe(...);
+actor.start();
```
19 changes: 19 additions & 0 deletions .changeset/lemon-mails-smoke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
'xstate': major
---

Observing an actor via `actor.subscribe(...)` no longer immediately receives the current snapshot. Instead, the current snapshot can be read from `actor.getSnapshot()`, and observers will receive snapshots only when a transition in the actor occurs.

```ts
const actor = interpret(machine);
actor.start();

// Late subscription; will not receive the current snapshot
actor.subscribe((state) => {
// Only called when the actor transitions
console.log(state);
});

// Instead, current snapshot can be read at any time
console.log(actor.getSnapshot());
```
1 change: 0 additions & 1 deletion examples/todo-mvc-svelte/src/Todos.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import { useMachine } from '@xstate/svelte';
const { state, send, service } = useMachine(todosMachine, { devTools: true });
// service.onTransition((state) => console.log(state));
$: ({ todo, todos, filter } = $state.context);
Expand Down
24 changes: 0 additions & 24 deletions packages/core/src/interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,25 +215,6 @@ export class Interpreter<
}
}

/*
* Adds a listener that is notified whenever a state transition happens. The listener is called with
* the next state and the event object that caused the state transition.
*
* @param listener The state listener
* @deprecated Use .subscribe(listener) instead
*/
public onTransition(listener: SnapshotListener<TBehavior>): this {
const observer = toObserver(listener);
this.observers.add(observer);

// Send current state to listener
if (this.status === ActorStatus.Running) {
observer.next?.(this.getSnapshot());
}

return this;
}

public subscribe(observer: Observer<SnapshotFrom<TBehavior>>): Subscription;
public subscribe(
nextListener?: (state: SnapshotFrom<TBehavior>) => void,
Expand All @@ -255,11 +236,6 @@ export class Interpreter<

this.observers.add(observer);

// Send current state to listener
if (this.status !== ActorStatus.NotStarted) {
observer.next?.(this.getSnapshot());
}

if (this.status === ActorStatus.Stopped) {
observer.complete?.();
this.observers.delete(observer);
Expand Down
17 changes: 11 additions & 6 deletions packages/core/src/waitFor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,18 @@ export function waitFor<TActorRef extends ActorRef<any, any>>(
sub?.unsubscribe();
};

function checkEmitted(emitted: SnapshotFrom<TActorRef>) {
if (predicate(emitted)) {
dispose();
res(emitted);
}
}

// See if the current snapshot already matches the predicate
checkEmitted(actorRef.getSnapshot());

const sub = actorRef.subscribe({
next: (emitted) => {
if (predicate(emitted)) {
dispose();
res(emitted);
}
},
next: checkEmitted,
error: (err) => {
dispose();
rej(err);
Expand Down
24 changes: 12 additions & 12 deletions packages/core/test/actor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -734,11 +734,11 @@ describe('actors', () => {
}
});

interpret(startMachine)
.onTransition(() => {
expect(count).toEqual(1);
})
.start();
const actor = interpret(startMachine);
actor.subscribe(() => {
expect(count).toEqual(1);
});
actor.start();
});

it('should only spawn an actor in an initial state of a child that gets invoked in the initial state of a parent when the parent gets started', () => {
Expand Down Expand Up @@ -868,13 +868,13 @@ describe('actors', () => {
}
});

const countService = interpret(countMachine)
.onTransition((state) => {
if (state.context.count?.getSnapshot() === 2) {
done();
}
})
.start();
const countService = interpret(countMachine);
countService.subscribe((state) => {
if (state.context.count?.getSnapshot() === 2) {
done();
}
});
countService.start();

countService.send({ type: 'INC' });
countService.send({ type: 'INC' });
Expand Down
10 changes: 2 additions & 8 deletions packages/core/test/assign.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,18 +398,12 @@ describe('assign meta', () => {
}
});

let state: any;

const service = interpret(parentMachine)
.onTransition((s) => {
state = s;
})
.start();
const service = interpret(parentMachine).start();

service.send({ type: 'PING_CHILD' });
service.send({ type: 'PING_CHILD' });

expect(state.context).toMatchInlineSnapshot(`
expect(service.getSnapshot().context).toMatchInlineSnapshot(`
{
"eventLog": [
{
Expand Down
16 changes: 8 additions & 8 deletions packages/core/test/event.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ describe('SCXML events', () => {
}
});

interpret(machine)
.onTransition((state) => {
if (state.done) {
expect(state.context.childOrigin).toEqual('callback_child');
done();
}
})
.start();
const actor = interpret(machine);
actor.subscribe((state) => {
if (state.done) {
expect(state.context.childOrigin).toEqual('callback_child');
done();
}
});
actor.start();
});

it('respond() should be able to respond to sender', (done) => {
Expand Down
7 changes: 3 additions & 4 deletions packages/core/test/final.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,11 @@ describe('final states', () => {
}
});

let _context: any;

const service = interpret(machine)
.onTransition((state) => (_context = state.context))
.onDone(() => {
expect(_context).toEqual({ revealedSecret: 'the secret' });
expect(service.getSnapshot().context).toEqual({
revealedSecret: 'the secret'
});
done();
})
.start();
Expand Down
8 changes: 6 additions & 2 deletions packages/core/test/input.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,16 @@ describe('input', () => {

const observableActor = interpret(observableBehavior, {
input: { count: 42 }
}).start();
});

observableActor.subscribe((state) => {
const sub = observableActor.subscribe((state) => {
if (state?.count !== 42) return;
expect(state).toEqual({ count: 42 });
done();
sub.unsubscribe();
});

observableActor.start();
});

it('should create a callback actor with input', (done) => {
Expand Down
Loading

0 comments on commit 234d416

Please sign in to comment.