Bug
I have a parent machine which sends an event to a child machine.
The child machines receives the event and updates its own context (tested and confirmed to be working)
Parent can fire off event multiple times and child's context updates accordingly.
I have a react component tied to the child machine through useMachine(ChildMachine) but the child does not rerender on the context update caused by the parents send event
If I use the local send event (const [state,send] = useMachine(ChildMachine)) then the template rerenders and receives the new state and all is well
The issue arises when I call the send event from the parent, then as said above the Child's context is being updated BUT the react component using useMachine(ChildMachine) does not rerender. Its like nothing happended.
Child machine rerenders when the context is updated
Child doe not rerender
I am unsure why the send event sent from a parent machine that does update a child's context does not cause a rerender when a send event triggered by the useMachine send tuple does. I assume it might be because they end up being 2 separate objects?
Yes they are two completely different machines. When you create a machine, e.g.:
const someMachine = Machine({ ... });
think of that as a _blueprint_ for the behavior of some object. You can use that "blueprint" to create a service with that behavior:
const someService = interpret(someMachine).start();
So, someMachine is pure. Its machine.transition() function is pure, it has no internal state. When you call useMachine(someMachine), it _creates_ a service for that component only.
You can share services with useService(someService).
Thanks for the reply.
3 questions
I feel that some of the issues I am opening are due to lack of understanding. Is there documentation / guides you recommend I can read / do to help clarify these concepts?
I understand the 'blueprint' concept that makes sense now, what I am unsure if then is how to have machines invoking / linked to a single instance of another machine, like the notification machine in the above example. So that any machine can invoke a notification for example and the notification component linked to the notification machine via useMachine or useService can then register the event.
Where can I read about useService a bit more to understand how and when to use it. The part where I feel stuck is that I want to invoke a machine in a machine, but I am not sure how to access that invoked machines context with the useMachine hook. If I use the useService method which service should I be using in that case, it seems as if I should be using the authService in the above example but I dont want a coupling between the notifications and auth, rather just a "subscription". I might be approaching machine completely from a wrong angle, so please bear with my questions :p
The official XState documentation 馃摉 should be your primary source.
A machine is a blueprint, and a service is a running, stateful instance of a machine. See the docs on services 馃摉 for more info.
So should I export the notificationService like this:
const notificationService = interpret(notificationMachine).start();
And then in the authMachine do the following
invoke: [
{
id: 'notification',
src: notificationService,
},
],
No, you should invoke the service in your parent machine:
{
invoke: [
{ id: 'notification', src: notificationMachine }
]
}
And then send notification events from children to the parent, which _owns_ the notification service:
// on child
{
actions: sendParent('UPDATED')
}
// on parent
on: {
UPDATED: {
actions: send('CHILD_UPDATED', { to: 'notification' })
}
}
We mentioned the useService Hook, then the interpretation of a machine to create a stateful instance and then about sending events from child to parent and from parent to child. I am a little confused.
send notification events from children to the parent, which owns the notification service
Does this mean that I need a machine which invokes the notification machine, so the notification machine is the child, and the child needs to send events to the parent machine, in this case the authMachine? Or that I have one central machine, which one if its children will be the notification machine, and other children can send events to the central parent, which then updates the notification machine?
Then the notification component must use useMachine(AuthMachine) to receive the updates, not sure how useService fits in here with the above child - to - parent idea in mind.
Don't worry about useService for now.
Here's a visual. The dotted lines are sent events.

Okay that helps. So in essence I need to create a "Root Machine", which invokes all of the other machines in the app?
Does this sound correct, or is it a signal that I am thinking about machines and the relationship between them in the wrong way?
I remember you saying that you should think of machines as independent API's sending requests to each other.
Yeah, typically, "actors" (which you can consider every entity/service) are hierarchical: https://doc.akka.io/docs/akka/2.5.4/scala/general/actor-systems.html#hierarchical-structure
Another way to think about it naturally is like an API gateway. You don't directly call various services from the client - instead, you call some sort of API (e.g., GET /api/users or POST /api/user) and the API then calls the appropriate service (and possibly sends a response to the client).
This naturally allows the "parent" (API gateway in this example) to do things invisible to the client, such as caching, throttling, etc.
Thanks for sharing that link, its got some good info.
When would you choose to use an XState Actor over invoking a service?
Finally, with the above diagram in mind, how should I then link a React component to the notification portion of the diagram so that it updates when a child event sends a event to the parent which then sends an event to the notification machine.
I understand that if I simply do useMachine(notificationMachine) I would then be creating a new stateful instance which then would Not be linked to the parent machines instance of the notification machine.
So that's where useService comes into play I assume? The implementation of that is not clear to me.
I assume I need to somehow export a notification service from the parent machine and use that in the React notification component with useService(NotificationService) ?
Let me know if my above comment is too lengthy and if I should write it out more succinctly.
Once I understand the above concept (or how I should rather think about it) I believe I should be able to move forward.
I looked at using a service as an action and that could work, but then in the documentation there is a comment saying do use services directly as actions but rather through invoke. Which leaves me with the above question again.
Take a UI-first approach here, since it's entirely a UI concern. Instead of dealing with a notificationService, I'd use a 3rd-party component (or build your own) and have notification dispatching be an action.
For example, with react-toastify, an action might look like:
import { toast } from 'react-toastify';
function toastAction(ctx, e) {
toast(e.message);
}
// ... in machine
{
actions: toastAction
}
Do you have an architectural pattern diagrams of general ways to utilize XState in apps, and with react if available?
I imagined I could replace redux completely with XState, and have different machines communicate to each other and those communications would trigger component renders.
The notification example was just an example, so toastify would solve that specific use-case, but the actual pattern of sending updates from machine to machine and have react register that is the tricky part.
Thank you for taking your time and helping out.
@EmirGluhbegovic
I created this example that may have some of what you are looking for. The machine is hooked into react context. That top level machine would communicate with other machines, essentially taking the place of redux, where the context takes the place of the store.
For anyone attempting to wrap their heads around using actors with the hierarchical approach described in here, I've put together a proof of concept that allows long-running tasks' states to be easily displayed as notifications.
https://codesandbox.io/s/xstate-tasks-and-alerts-poc-yotik
There are 5 machines that are interacting to simulate a real-world use-case:
alertsRef and tasksRef actorALERT.ADD events, sending the event to the alertsRef actorADD_ALERT events that the app machine sendsALERT.ADD events to the parent app machine based on whether the task has started, resolved, or failedOne improvement would be to encapsulate the app machine using React's Context, so that one would have access to the services at any level of the component hierarchy.
@larrybotha although working, it doesn't seem to be very efficient. In your example you are spawning new task and alert actors every time you add a task. All those services are orphans and will keep living in memory.
@matchatype ye, very much a proof of concept while I was trying to understand how everything fits together - at the very least those actors all need a .stop() when removed
Also, thank you for sharing that!