Everything is an Actor
Watch on YouTube (React Finland)
What is this talk about?
“You can send a reference of another actor to some actor so that the actor you send the message to can communicate with that actor.”
“An actor can also create or spawn a finite number of child actors, and these child actors are just like every other actor.”
From the opening of the talk.
Key takeaways
- We don't want to model absolutely everything as actors, and since all computation can become, can be performed within an actor, it can also contain its own behavior and state. 10:00
- You can send a reference of another actor to some actor so that the actor you send the message to can communicate with that actor. 13:00
- In some implementations, like Akka, every single actor from the root actor has exactly one parent. 17:00
- XD can also invoke and spawn child actors, and so invoking an actor is done. 23:00
- The main idea is that you will create some sort of parents actor using used machine. 32:00
Quoted from the transcript.
Full transcript
From YouTube auto-captions. Punctuation and capitals were restored automatically. Technical terms were normalized; some errors remain. 7,106 words.
0:00 Introduction
Hey everyone, my name is David Khourshid, also known as David K. Piano. Pretty much everywhere online. So today we're going to be talking about how everything is an actor. It's sort of a strange title for a presentation, but we're going to see, hopefully in the next half hour, how this philosophy makes sense in terms of programming. Any sort of reactive application, uh. Furthermore, we're going to be exploring how viewing our applications as complex systems of actors, all communicating with each other, can even simplify and improve the way that we organize our logic. But when I say everything is nectar, I do really mean everything. So let's consider a real life example from better times, when there wasn't a pandemic that was completely interrupting our way of living. Suppose that you wanted to go to your favorite cafe and sit down and get some work done? Which is something I love to do instead of being stuck at home. So we're going to use this dotted line to represent sort of a timeline of the events that happen.
When we're going to this hypothetical, magical cafe that we could all socialize in, and, you know, live our normal lives. So you walk up to the cashier, right? And you ask for a coffee in. The cashier then has to tell the barista what the coffee order is so that they can start making it. And so in the meantime, the cashier tells you that it will be three euro and you're okay with that, so you get your credit card out and you pay the three euro. So now that the payments is made, you probably have to go through a payment processor. Like, maybe you have a square thing or a little terminal on the on the counter. And so that itself might be a series of events where we're sending payment information to a payment gateway and we're getting credit card information. And maybe you're also leaving a tip, or you're registering your phone number for reward points. If they have any sort of frequent customer like appreciation sort of thing, and you know, whatever else.
A payment platform may do so. When you've made your payment, the cashier then gives you a receipt, and then you wait a few minutes while the barista prepares the coffee. When? The coffee is ready, the barista gives the coffee to the cashier, who then delivers it to you. So getting a cup of coffee from a cafe in the morning involves a lot more communication than you may think. In fact, there might be more employers, there might be more coordination going on, and this isn't always the way that things work, too. I mean, the espresso machine might be broken, or we might be out of supplies, or we might be in the middle of serving more than one customer at the same time. So there's this idea called eventual consistency that states that in a distributed system. Everything that's observing some sort of value will eventually get the latest value, as long as that value doesn't have any new updates. So in software, you know where you typically want to know the value as soon as possible.
This can be a little bit frustrating, but in real life, it makes sense. If something happens somewhere in the world, which, you know, has happened far too many times in 2020. Not everyone's going to know about it immediately, you know? Some people might post about it on Twitter, or it might show up on the news, and eventually everyone who cares will know about it. But the key point is that it doesn't happen immediately, and it happens due to communication. So let's let's take a little bit of a nicer example. When you went to the cafe, you want coffee, right? So the barista doesn't know that, you know? Although they could probably guess they're coming in here. They probably want a coffee, but they can't read your mind, uh? But they'll eventually know that you would like a coffee, if they care to ask, what would you like? And so the facts that you want to copy is part of your internal private state.
Again, no one can read your mind. If you're tired or you're hungry, nobody knows that unless they ask you or you tell them. So you can choose to share that internal state by replying, I would like a coffee, please. And so when you say that statement, in effect, it's immutable, it has been said, you've said it, you can't go back in time and you can't change that statement. And so if you wanted T instead, you could say afterwards, actually. I, I want some tea. But that doesn't change the fact that you said you wanted coffee first, and the barista knows for the cashier knows that you asked for a coffee first.
5:00 You can send a reference of another actor to some actor…
So, of course, asking for a coffee isn't a guarantee that you're going to get a copy. Just like making an API request to a server, whether you're using REST or GraphQL or whatever. It's not any guarantee that the server is actually going to come back with a response. I mean, they could sign out, you could get a server error, which I guess it is sort of a response, but you know what I mean? But anyway, if all goes well, you'll eventually get your coffee. And so all this is done through message passing. And so we could consider each individual in this scenario to be what's called an actor. And these actors communicate with each other to achieve a certain outcome. And so this is a. It's an interesting way of viewing how things work in real life, because it is actually how things work in real life.
And this is also how things work in the actor model. All right, so what is an actor? In short? An actor you could think of as an abstraction that describes pretty much everything. An actor can be thought of as any entity that can send or receive messages, so an actor can react to messages. Meaning that when they get a message, and only when they get a message, they can do something. And so we're going to talk about what that something is soon. So, in terms of programming, an actor can send a message or an event, or a signal. I use all those terms interchangeably, so an actor can send a message to another actor that it has reference to sending a message. In programming is, you know, basically a function call, it's exactly the same thing, so, just like you can talk to people that you know or you are in contact with, actors can only talk to known actors.
But just like email or phone calls, you can include a reference to yourself so that the recipient actor can say, Okay, there's your email, I can reply to you. And so when the actor receives a message, it can decide what to do with that message. In this case, when an actor is greeted, then it could decide to send back a message, although, you know, in this case, it is finished, so it doesn't have much to say back. So the actor model, just like, you know everything I talk about St. Machine statecharts, whatever, it is nothing new. In fact, the actor model is even older than statecharts. Which I don't, you know, talking about for a while, uh. The actor model was first formulated in the early 1970s by Carl Hewitt, along with Peter Bishop and Richard Steiger, in the paper, titled A Universal, Modular actor. Formalism for artificial intelligence. So, yeah, they were talking about artificial intelligence way back then, and even further back from that.
And so, this paper was interesting because it, it took views from physics on, just this idea of there being actors communicating with each other. And it was also influenced by the small talk language, which was created by Allen key. And you might know Elky as the computer scientist who coined the term object-oriented programming. But what's interesting is that Algae envisioned object oriented programming, which is commonly viewed as everything is an object with more of a message passing approach, and that's something that the small talk language actually emphasized. Allen key himself said that the original vision of object-oriented programming was basically the actor model. And, if you? If you go to this link, you will see a discussion where allen key says that. There is almost virtually no difference between, his original vision for object oriented programming and the actor model that, Carl Hewitt and others have created. So now, while many computer science models are based on mathematical models, the actor model itself is based on physics, like general relativity and quantum mechanics.
So, how it relates exactly is beyond the scope of this dock. So I'd like to think of the actor model as relating to real life instead, because it makes things a little bit simpler. Okay, so let's define actors concretely. They have a few basic rules, and these rules have remained unchanged for basically the last 50 years. Just like we have rules and React about render purity and immutability, these rules are what make the actor model work so well in distributed and concurrent systems. So the first rule is about locality. All computation is performed within an actor only, and so, as per the title of this presentation, everything is an actor, because the actor is a fundamental unit of computation. In fact, you could model pretty much everything in programming as actors, even individual values, you could consider them to be little actors. Where you ask it what its value is, and it immediately gives you a response back, but that quickly becomes unpragmatic.
We don't want to model absolutely everything as actors, and since all computation can become, can be performed within an actor, it can also contain its own behavior and state. Which is something that, you know, we could sort of think about both of those as the same thing. We'll talk about that a little bit later. Basically, actors can be stateful or stateless, and they can have their own private states. And if an actor wants to do any sort of external communication, it spawns another actor to take care of that again, just like in real life. So then how can one actor read another actor's states? Well, so that's where the second rule comes in actors can communicate only through messages, nothing else. Like, what's this thing? Isaac Newton said for every accident, there's an equal and opposite reaction, but you can't have a reaction without an action. I mean, something has to cause something to happen, and so that something is. Messages, messages are immutable, which provides a guarantee of no shared state between actors.
And so this itself just defeats a whole host of concurrency problems, like, deadlocks and race conditions and things like that. And so if one actor wanted to read another actor's date, it needs to ask it via a message or need to be told via message. The receiving actor can then decide whether or not to send back a message containing the desired piece of states that the other actor wants. And so, if you think about actors. The same way as communicating between clients and server via HTTP, that's basically the same idea. When you ask for something from an API, you're not going to get a result back immediately. And you have to send what's called a request, you're sending a get or a post request, or, you know, put. Deletes whatever else you might send, and you might or might not get back some information, which itself is a message.
So that's basically the same idea. So actors are reactive and that they react to incoming messages, and there are three things that an actor can do when it receives a message. First of all, it can change its local state or its behavior. Remember that an actor can have local isolated state, which includes the data and the logic that determines what an actor should do in response to any given message. For example, if you send an increment message to some sort of counteractor, it can change its internal states to its current count. Plus one, it can also determine that the counter has reached its max. And so that you could consider its behavior, and given that, it could change its behavior so that nothing happens if another increments message comes. So that's what we mean by behavior, and we'll go about that a little bit more later. So an actor can also send messages to other actors that, of course, it knows about, and so this makes sense in real life, too.
You can only talk to people that you have contact with. If you want to email someone, you need their email addresses over to email them. You can't just randomly put in someone's name and hope that you know it reaches the right person. So just like you can send someone's Twitter handle or email address to someone. You can send a reference of another actor to some actor so that the actor you send the message to can communicate with that actor. An actor can also create or spawn a finite number of child actors, and these child actors are just like every other actor. They follow the exact same rules, they have their own isolated state, and they have their own behavior. So remember that an actor can only know of some external state if it receives it via a message, or if it's born with that information. Sort of like genetics, that is, the parents can create a child actor that already has some relevant data from its inception, you know, just like real life.
So even though actors all follow the same rules, they can behave a little bit differently in reaction to a message that they receive. And. This is what's called the actors behavior, and this is what determines what immediately happens next due to some sort of incoming message. A finite state machine is a really great way, or says, that you can describe a behavior of an actor. Since it's an events driven approach to modeling logic. And by the way, like I mentioned, I use message and event interchangeably, so you could consider them the same thing. Whenever I switch up those terms. With a state machine, the finite state represents the qualitative state, and in different finite states, events can do different things or transition to another states. State machines can also have extended state, which represents the quantitative data associated with that machine. So in this example, we could have orders, inventory or sales, and all of those pieces of data are extended.
State. Which don't really have anything to do with the behavior. And behavior can include things like being idle, you know, waiting for someone to make an order, making coffee or delivering coffee. So, both of these combined make up an actor's overall state, which is why an actress behavior can be expressed. You know, as it states, and we could use those both together. And, of course, if you're not using a state machine, you might have his loading booleans floating around, or his error is success, whatever. And so hopefully you have some logic that does the right thing, depending on if is loading or is. Is true or false. And so that's the same thing around behavior, uh. We're basically determining what should happen next, given the current state and the event that just happened, or the message that was just received. So, whereas an actor's behavior represents its internal logic, an actor system represents the connections between all of the actors.
And so this is where we sort of deviate from, from typical state management solutions. Because the truth is, there is no single source of truth, there is no single atomic state store.
17:00 The child window actor has a reference to the parents window…
In fact, state can come from many, many different places. And so instead of fighting against that, the actor system embraces that. And so an actor system always has a single root actor, which is known as the guardian actor. In some implementations, like Akka, every single actor from the root actor has exactly one parent. So. Enactor system forms a hierarchy, or sort of a tree structure. And remember that any actor can spawn any number of child actors, and these child actors can themselves spawn child actors. And on and on, and so that's how it forms a tree. And so each actor has a unique address that identifies it for simplicity, in some actor model implementations, this actor address represents the hierarchical path to the actor. For example, in in over here, cafe manager one is a child of cafe, and cafe manager one employee one is a child of that manager. One parent's actor addresses can't be used to access the actor instance directly.
So just like if you have my email address, you can't access my email inbox. Or at least I, I really, really, really hope not. You can only send me a message using my email address, just like an actor can only send messages to other actors via their address, and just like an email inbox. Those messages arrive in the actor's mailbox, you see, so we're making the analogy there, and that's how an actor can process one message at a time. So let's talk about mailboxes for a bit. An actor needs this. This idea called a mailbox to guarantee that only one message is sent at a time. And here's why when an actor receives a message, it needs to process that message to determine what happens next. How its state is going to change. What the next behavior is, if it needs to spawn new actors or send messages to other actors, etc. Etc.
When it's done processing that message, it can then process another message and return the next state. But what happens if an actor is processing a message and then it receives another message? You know, immediately during the processing of that current message? So this can lead to race conditions or impossible states, or worse. It could actually make the actor crash. So how can we prevent this from happening? Well, we could use mailbox, and by using a mailbox, we can hold all of the messages in some sort of queue. The actor can then DQ these messages one at a time, so this guarantees that, we only get one message at a time. The actor takes the DQ'd message, determines the next state, performs. Any side effects? And only then does it. DQ the next message. So even if a message arrives as the actor is processing the previous message, the mailbox will hold on to the message until it's ready for processing. And that's, that's basically the role of a mailbox.
It's also interesting to note that the mailbox itself can be represented as an actor. Now remember that an actor instance can't be accessed directly. We can only communicate with that actor using some sort of address, or, in other words, some sort of reference to that actor. And this gives actors what is called location transparency, and that allows the actors to act sort of like a black box. Because we don't really need to care where the actor is, we just need to access, something that references the actor and the actor. Wrath itself will take care of forwarding the message to the actual location of the actor. Whether it's an outer space or on some local box somewhere, doesn't matter, and we're not really supposed to know anyway. And if you think about it, this also means that we could hot swap an actor while the program is running, and it will still work exactly the same. And this is why, this is why actors work so well in, in concurrence and distributed systems.
And so this location transparency also enables another really powerful feature, which is false tolerance. If an actor fails for whatever reason, whether it's a shaking network or some other fatal error. Some aftermodel implementations can choose some sort of strategy for reviving that actor, or even letting it fail gracefully. That means that if one actor fails, it's not going to take down the entire system because it shouldn't, right. If you have some sort of runtime error in your application, like in a very small part, that doesn't mean that your entire application should fail necessarily. So, one such strategy that some implementations use is to just, restart the actor if it fails, or replace that behavior with some sort of fallback behavior. So this provides a lot of resiliency to, to actors, so, like I said from the very first slide, everything is an actor. And hopefully now, if you squint, you'll begin to see how various parts of our code can really be modeled with. This message passing paradigm I.
I was recently working on the post message API. And I realized that. The way that windows communicate with each other, whether it's an iframe or a pop-up window or DevTools panel, is with message passing. I mean, it's even in the name, post message. So, let's say that we spawn a window actor by calling window.open see, sort of pretty much the same thing. And then the parent window actor can send a message to the spawned child window by calling post message. And so the child window actor has a reference to the parents window actor in the source property of the message. Which is something I recently learned about, which is really useful and it can use that to send a message back to the parent. So now you have this parent's child communication going on. So the reason I'm talking about how everything is accurate is because this is true for X data as well.
Now, XState library that I created is mainly a state machine and statecharts library. I've given a few presentations on them, especially at React Finland. So I really encourage you to go back and watch those presentations if you want to learn more about XState. And so, from those presentations, you'll recall that state machines and statecharts describe the behavior, and in this case, they describe the behavior of a single instance of an actor. But XD can also invoke and spawn child actors, and so invoking an actor is done. Using the invoke property inside of a state, the behavior of an actor is specified in the source property. So in this case, we're invoking a new actor, with the behavior defined in espresso machine, and when this actor is done, we transition to the deriving coffin or, sorry, delivering coffee states. By the way, invoking and spawning are pretty much the same thing.
I know it's a little bit confusing. But the only difference is that an invoked actor lives for only as long as the machine is. In. That states, where that actor is defined, so once we exit that states, the actor is automatically stopped. Pretty much the only difference. And, if you spawn actors, you have to, man, manually stop them. So, there's no special way for X8 or any sort of actor. And any actor model implementation, to know whether an actor is done or not. Done is just a message, and so that's why the invoked actor has to spend. Send that special done message back to the cafe machine. So when we invoke the espresso machine, we're creating a new actor with, with espresso machine behavior. And that actor should eventually send that special done.invoke.espresso machine back to the parents. If you're wondering about why it's named that way, this syntax for that in that done invoke message is defined in the SCXML spec itself, which XState the tears to?
So, now because the caffeine machine has a reference to the invoked actor, because, you know, because it invoked it. It can send events to it, for example, if the cafe machine gets a change order event, it can send that event, or pretty much any other events directly to the invoked espresso actor. Referencing it by its ID in the machine. And so internally, XD keeps a reference to all of those actors, and it matches those IDs with those references. So the idea is just an abstraction. If it seems a bit verbose, there's a helper function in XC called forward two. And so all that means is take the exact same message you received and forward it to that actor. So in the Evo, in the Invo, ah, in the invoked espresso machine, the actor already has a reference to its parents. So we can send the parents cafe machine events such as machine broken.
If the machine breaks, then the parents can decide that it needs to handle that event. And decide. You know what to do next now? Sometimes we need to spawn actors dynamically, such as whenever an order comes in, so, you know, instead of being constrained to a state. And that's what spawn is for. For instance, whenever an order is placed, we can spawn order actors, which each have their own behavior specific to handling orders. Since these actors are fundamental units like Carl, he would describe, they can be treated as values themselves and assigned to context. Just like any other data, like an array or an object, or a number, or a string, or whatever. Uh. Also, note the second arguments to spawn, which is a unique identifier for that actor, that. Events dot order ID that's how the parent's machine can send messages to the spawned actors later.
So, for example, if we need to cancel an order, we can send the cancel events to that specific order. And that will pick up the events. And do whatever logic it needs to do, you know, to cancel that order. The upcoming XD version five is taking this. Everything is an actor approach to the next level by simplifying how it creates and works with actors.
28:00 At first, I didn't think that promises can receive anything…
In version 4, it treated promises, observables, callbacks and other machines very special by internally adapting them to be actors. And so this made general use case is easy, because it automatically did that for you, but it made other use cases harder. And so in version 5, this will need to be explicit. You will only be able to create and communicate with actors. So helper functions are going to make it easy to invoke actors such as promises. And also to spawn with. And so this is going to enable XDA to be truly universal. Because, it will now be able to spawn and communicate with pretty much anything. That has an actor interface, and, like I said, everything is an actor, so in general, an actor can send and receive pretty much any kind of events. So how can we consider other constructs, like promises and observables, to be actors themselves? So a promise can be considered an actor?
That can only ever send back at most one message, a resolved or rejected value. So at first, I didn't think that promises can receive anything, but in the browser, you can send in the board controller abort signal to a promise. To avoid it. There's, you know, that's about the only thing that a promise can receive, there's no other type of communication that you could have with promises. You can't send anything in flight. You know that's what things like websockets and other streams are for. So, observables are like promises, but they can emit multiple values over time instead of just a single value over time. And so, observables can also emit a completion signal or an error signal. And when it sends one of those signals, the observable is then terminated, and it could send no more values in the TC39 observable.
30:00 If you pass that child actor anywhere to any component…
Spec, which hasn't been, you know, accepted or finalized, but we're still going to use it. It isn't specified that observables can, can receive any events, so in essence, they're one-way streams of data. However, RxJS, which is a very popular observable library, has what are known as subjects for this. And subjects can receive values and then emit those values directly and internally. An observable has some sort of source where it generates values, and that source can also act as something that receives values. If you, if you look at it that way, in short, observables, can you know? They still have that same message passing, idea, so they can be considered actors as well. Now, React is a whole different story. If you have a parent's components that creates a child component, then it's pretty trivial to send in events from the child to the parents. We do this all the time, we just register an event handler as a function prop for the child, but sending in events from appearance to child is a whole different story.
And of course, you could use context and do some sort of Redux sort of thing to achieve this. Or if you don't want to use context, you could use hooks like use imperative handle, which is probably that hook that you never thought that you would touch in your life. And you could also use Rep to keep a reference to that imperative handle that you pass to the child. And it could sort be used that way. But long story short, it's, there's no direct way to send some sort of transient, time-based event from appearance to a child component. Mainly because React wasn't really built this way, React propagates changes via props, and as props are its main method of communication. When the parent component is communicating with a child, it's doing so by changing its props. And the child component then has to interpret the fact that its props changed.
And so it needs to act accordingly. And this is made even more difficult by Reacts not being able to tell you which one of those props changed. Or, you know, maybe the local components they changed instead, and that's what caused a re-render, so maybe no props even changed at all, and so neither of those things. Are as explicit as a single time-based event. Now, since XState embraces the actor model, you can use the hooks and XState reacts in order to achieve this. The main idea is that you will create some sort of parents actor using used machine. And that itself can create its own child actors, like we've seen with invoking spawn, that child actor. Since. It's just a value, it's just an object that you could pass anywhere. That actor is passed as a prop to the child component, now that the child component has the child actor, and the parent component has the parents actor.
Both commun, both components can communicate with each other via message passing between those actors in XState and so in X8 reacts. There's this useMachine hook that is used to reference, to uh. To actually create that actor from that machine, and that actor in that machine. We're going to, we. We could create child actors, and, that might live in an array of actors that, you know. In this case, we call state.context.orders, and so we could pass each of those order actors to the order component. And again, this is just a value, just another, prop that you're passing to a component. And so that gives us the actors current states, and it also gives us a function to send messages to that actor. So for example, when we, send the cancel events, that might, in turn, send cancel over to the parents actor. And then the parent actor would know what to do. Long story short, using the useMachine and you service hooks is what allows you to do that.
Parent child communication in React, or it doesn't even have to be necessarily parent's child. If you pass that child actor anywhere to any component, it will have a reference to that actor and still be able to communicate in exactly the same way. So there's a few, programming languages which, really evolved and embraced. This actor model that was originally created by Carl Hewitt and, you know, Allen key. And the most popular one, or the most well-known one, I would say, is probably Erling, created by Joe Armstrong. And so this is a language that's heavily used in telecommunications, which is where the actor model really. Shines because it's this distributed computing environment. Now. Elixir is also built on the Erlang virtual machine. It's another popular language, and it's basically Ruby for Erlang. Akka is built on Scala, which is on the JVM, not the early virtual machine. And it's probably the most popular actor model implementation or framework out there in the wild.
There's even Akka..js and Akka..net. And Pony is another lesser known object-oriented actor model based languages, or language. Now there's a lot of actor model implementations in JavaScript too, but I'm excited to introduce X actor, which is a new actor model implementation in JavaScript that works seamlessly. With or without XState, it's not different the next state, it directly integrates with it, so please stay tuned for more information. And with that said, I hope you can take your newfound knowledge of the actor model and apply it to, to you. All of your applications, with or without any libraries. Thank you, React, thank you so much, David. That was a really, really good talk. I'm always amazed how smart you are. I know that I've said this several times, but I'm still always amazed at how smart you are, which is kind of nice. Thank you. Okay, so we do have some questions. I know that you're on the QA channel, but I need to.
It's my job to ask you these questions. All right, so first, the first question is, if someone is wondering about the different uses of the actor model and how the model of this idea of this model is different than event driven models, so the actor model is an events driven model. In exactly the same way, that or not, exactly the same way. But like, how you would think about Redux? So, I guess one of the best points of comparison is Redux, and I actually wrote an article about that.
37:00 Even though, Redux tries to make it seem like, Oh…
But basically, with Redux you have a single store, it is a global atomic store. This is the place where you send all of your events and all of the state gets updated. Even though, Redux tries to make it seem like, Oh, we have combined reducers, and you could have everything separated between those reducers. A lot of the times, you have questions about, first of all, what if you don't want? Other reducers to care about the events, also, what if you want other reducers to talk to each other even and be their own entities? And so this idea of a single global atomic state starts to break down really quickly. Because all of our front end apps, and you know, any application that we have, is essentially a distributed system, you know, if we think about it that way. So where the actor model differs is it treats every one of these quote-unquote reducers as little entities. And each one of those could talk to each other, via events.
So that's one of the biggest differences, that you would see between, you know, something like Redux and the actor model, which, again, is definitely a very events driven. You know, methodology. Not good, cool, so that was perfect sense. Yeah, I posted that link in the chat, yeah, the yeah, it's posted on the mini Comp QA chat. If you want to check out the link that David was talking about, where he talks about Redux and a lot of these patterns. And the second question that I have, I think you're gonna have to read it. And if you want to read, because it does contain code. And if you, the ones that are listening, want to read it, please join our Slack. But it's about explaining how you would maybe go around doing something like, right, what Matt is explaining? Yeah, yeah, so he, he explained. Actually, he.
39:00 Appearance to child communication mechanism is limited by props…
He mentioned that I already talked about it in the talk, which is pretty funny. But, it is a question I could go a little bit deeper into. It's basically, how would you model a message that's passed down from a React component to a child? Can the prop changing be modeled as a message? This is one of the most frustrating parts about React I love reacts. But it's frustrating that basically the way that a parent communicates with the child is. Hey, guess what? Something changed? And then the child's like, what changed? And the parents like, I don't know, maybe one of your props? And it's like, Okay, which prop changed? And the parents like, I don't know. Just render the entire thing, I don't care exactly, just re-render the entire thing. This works most of the. Time, however, when your prop, or when you want to model something, not as a prop changing, but as an ephemeral, transient event that happens in time.
That's not gonna work. So that's why there's, there's just a whole bunch of different things that you could do. You don't need a library in order to do it. You could use context, I don't know, there's also use imperative handle, which sort of does that same sort of thing, but long story short, reacts. Appearance to child communication mechanism is limited by props, whereas with a child to appearance. You just use a callback prompt and then you're good to go. Yeah, okay, cool, yeah. So that's all of the questions that we have. And I want to thank you so much David for coming. If anyone has any questions. We still do have two minutes and it would be great otherwise. Okay, okay, okay, I have been told something here by the mic, cool. So the what I got from the mic was. Have conversation with David. Okay, so David, you don't know about this conversation.
This has happened before, literally like an hour ago. Or it was like, need to have conversation with David?
41:00 In fact, you already know all about the actor Mall just…
Okay, David? Are you working on anything else? Like, I know you're working on a lot of stuff? But if there's anything that you would like to bring to the table of things that you're working on, that would be. This will be the perfect time to talk about it. Yeah, so sure, I actually. I'll talk a little bit about what I just posted in the chat. It's a library called X actor, you know, very similar to XState, and, this isn't something that's completely different than X Dated. In fact, X actor is going to, essentially, hopefully be a part of XState version five. It represents just the actor model parts of XState. So it's a lot less deep of a learning curve. In fact, you already know all about the actor Mall just by watching the presentation, that I showed, but where the actor Mall gets fun. It's just all of the different, ways you could design and model how the actors talk to each other, and things like that, so X actor.
Is meant to be a library. That, again, much lower learning curve than XState. And, a way to model your application with actors, so you could think of it as distributed. Redux. It still uses reducers and things like that. Basically, you give it a reducer in an initial state, just like useReducer. And that constitutes one behavior, and an actor can use that behavior. Basically, the behavior is like the brain, so, you know, just put the brain into an actor and it works. And then you can create a system of actors with a root behavior that talks to all of these other actors. And and yeah, you could subscribe to state changes, and things like that. In fact, the library right now is only 1.5 kilobytes minified in gZip, and that's without me even trying. So it's supposed to be a really small, you know, contained actor model implementation, so that's what I'm currently working on right now.
43:00 Definitely start with XState x actor
Just say that. If someone wants to start with this kind of visualization of state, would you tell them to start with XState or x-acto? I would definitely tell them to start with XState. X-Actor is definitely like. Despite it being a simpler library, it's for more advanced use cases. Because now you're talking about, what if I don't? Just want? A single reducer, which most of the time when you're using React, all you need is a single reducer for your components. But now, when you need something like, like, let's say you're managing a to do app, are, you know, our favorite, most common example? Yeah, yeah. So the actor that manages the to do's could be well, could be modeled as its own after, and then each single to do can be modeled as an individual actor. Essentially, it has a mind of its own, and so each to do can. Yeah, it can even do other things like fetch data and update itself and send messages back to the parents.
But yeah, so definitely start with XState x actor. It depends on your use case. Yeah, okay, yeah, that makes sense. Sorry, go, go, go. I was gonna say, it's not production ready yet, you know, it's still working. People don't listen to that. David I. I have it like three times in the. Repo so hopefully they'll listen to it. Okay, yeah, cool. Thank you so much David. It was really nice talking to you and I'll see you a bit later. And now we're gonna go to our next speaker. Thank you David.
Related talks
-
Putting the "Act" in Reactive: From Observables to Actors
RxJS Live! London, 2021. 38:31, 1.6K views -
Webinar: Get started with XState v5
Stately webinar, 2023. 1:13:11, 11.3K views -
Webinar: State Machines and Actors with XState v5
Stately webinar/stream, 2024. 2:42:16, 7.5K views -
The Actor Model, Behind the Scenes
JSConf, 2024. 32:42, 4.4K views