XState - Data Loading Service - Finite State Machines in React

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey how's it going it's Lee Halladay and we're playing with the X state library which allows us to build finite state machines in JavaScript and we're also integrating it into our react app and the state machine we're going to build today will be one that helps manage loading data we've got a list of data where we load say the first ten items then we load the next ten next ten until we run out of data and we want to manage all of that with this state machine I'm in this cool visualizer tool that X state has and allows us to see our state machines as we build it so we're actually gonna start building it here and then we'll copy it into our react code in a little bit umm the only thing I have so far is some dummy data here it's just an array of 25 elements and then how many items we want to load sort of every time we go to fetch new data from our data source so we'll start with a variable called the data machine and we'll initialize a new machine so anytime you have a machine you want to give it an ID it's like its name basically and we want to tell it what state is should be at the beginning when it first fires up so we're gonna fetch data right away as soon as it sort of kicks off so we'll make the initial state loading but let's see what states we actually have to work with so we'll define our state's property so this is where it gets its name the finite state machine because there's a finite number of states that this machine can transition from one to the next so we will have a loading state and we'll just make it an empty object for now and we'll fill it in later so after it's done loading with we've got basically two states we're gonna work with the first we'll call Moore basically it's done but there's still more data we could fetch from the server complete meaning we're done loading the data but there is no more we're complete and then we've got the failure state which is if it if there's an error connecting to the the server or whatever it will transition to failure so if we update this visualization now we can visualize our four states loading more complete failure and we see that it starts at the loading state now acts state provides a way to sort of indicate that some states are the final ones you can't really transition anywhere once you get to them so we'll define here that this is a type of final and this one is also a type of final because if it's a failure or complete there's nothing else to do so that just changes the visualization and indicates that it's final alright so the next thing we want to do is tell it how it can transition from one state to the next and does that by listening to events so the events were going to have so when we're in loading what events are we listening to so we'll say on so we'll listen to done and there's more so that would transition it to the the more state it could be done and it's complete so that would transition to the complete state or it could fail which would transition it to the failure state so if we update our visualization we can now see that we go from loading if it's done more it would go to more or if it's done complete it would go to complete etc so what happens if we arrive to more we basically want to give it a way to go back to loading and go fetch additional data from the server so that means our more state will listen to an event called load which will tell it to go back to the loading state this now now we can see the loop so we start in loading it's done but there's more we tell it to go fetch more it's done but there's more and then finally it's done but it's complete and we end up in the complete state so these are our finite states that we have to work with and how it can basically transition from one state to the next but we're missing something what about the actual data we want to load so state machines all of your data isn't these finite number of states you've got quantitative data that doesn't really fit into one or the other because we've got data available to us when we're both in the more and when we're in the complete so exte gives us a way to manage this using the context so context is where you define sort of all of your quantitative information so we're going to keep track of the data that we have and why don't we at this point transition from this visualization tool into our actual code so I've just copied and pasted this and we're going to go into a react app and after I paste this I'll quickly give an explanation about what's going on so we've imported use machine from XD react that allows us to basically inject a machine and listen for updates to it within a react component this is the machine that I created an instance of and we'll talk about a sign in a little bit down here we have our actual component the app and right now it's rendering a div where we have a list inside of it and this is where we'll eventually be mapping through our data to show a list item for every row of data that we have right now it's just an empty array we're gonna show when the data is currently being loaded from the server and will also give a button where we can tell it to go fetch more so if you want to see what it looks like right now we are showing the loading and we're showing the button yeah but it's not doing anything so let's start to hook it up into our state machine so the next thing we're going to do is that state machines in X state give you a way to basically invoke the service when it transitions into a state so we will use the property invoke so what are you able to invoke you can invoke sort of nested state machines that live inside of this parent you can invoke a promise which is itself sort of like a state machine because promises have pending resolved and failure states but the one we're going to be using is a callback so we're going to give it a name called the data loader and we'll define what this callback looks like so when you use a callback callback type of service that you want to invoke it's a little bit complicated because you need to define a function so this function receives the current context which is all of our data here it receives an event so how did we arrive to the loading state what event sent us there but work gets a little bit tricky is that we actually have to return another function and what this function receives is a callback and an on event so what are these things callback is a way to basically send events back up to the parent machine so we're able to send events to our data machine and what events are we going to send basically done more done complete or fail we can also - listen - we can listen to events coming from our parent so maybe other actors are sending events to our state machine like maybe someone wants to cancel loading data so we can listen to this and maybe cancel the Axios call that we'd be making but in our case right now we're actually not going to use these two and we're just going to focus on context and callback so what do we want to do here the first thing that we want to do is how about we the first thing that we want to do inside of this function here is access the current data that we have so we can put that into a variable called data and it's context like that the next thing that we want to do is basically go fetch new data from our data source which is this array up here so we'll say Const no data and what are we going to do we're just going to slice some data off of this array so with slice you give it a starting point in an ending point so where we want to start is just the length of our current data so at the beginning it's empty meaning length of 0 so slicing at 0 will get us the first start at the zeroth element of our array which is perfect and we want to go up until in this case we're fetching it 10 records at a time so we do data dot length plus per page okay so next now there's a couple events we could send it's either done but there's more or it's done but it's complete so why don't we create a variable called has more and the way we'll determine if there's actually more is we'll just look at the data that we just got from our data source the length of that is that equal to the per page if so if if 10 is here and 10 is here we're going to assume that there's more data to fetch if we were only able to grab five from the array well then there's no more that we can load so now what we can do is use this in an if statement where we've got an else as well and we can send events up to our parent mission based on that so the way you do that is you use the callback function so callback we're going to tell it which type of that that we're sending so this one would be done more and then we can pass additional data that we want to send to that event and we'll look at how to handle that in a second so we're going to be passing our new data to this event okay so down here we have another callback where we're doing a type of done complete and we also want to send data when it's complete in this case there's really no way to trigger the fail because we're just slicing data from an array but you can imagine that if this was grabbing data from like an Axios call on a server maybe you'd want to have a try-catch and when you catch it you could do a callback with the fail event to kick it over to the failure State now because our data source is instant just because it's an array why don't we actually put it in a set timeout so we can just sort of simulate a little bit of slowness so that we can really see that it's loading now we've got data so we'll just take all of this and put it into a set timeout and we'll give it a thousand milliseconds said one second of wait time so what we've done is we've called the callback function we've told it what event we're sending and we've given it the new data but now we have to in this event here basically handle this new data because we need a way to add it to our context up here so the way we can do that is by converting this into an object where this one here we have to tell it where we want it to transition to once this event occurs and I'll just save it like that so when this happens we transition to more and we can also add the actions property so actions are basically functions that we want to call when this event is is captured so now we're going to use that assign function that we imported so assigns all about updating data in the context this guy up here so what we do is we call a sign and we give it an object and we say that we want to update the data property of the context and the way we do that is by giving it a function and this function receives the current context sort of our current state and information about the event and our goal is to basically produce the new data that should be sent up and placed in the context so the way we'll do that is we will take our array and we'll add on the existing data and then we'll add on the event new data like that so we could clean a little bit actually we could be structure out the data property from the context and then we could access the new data from the event and we could even give it a default value just in case for whatever reason we're not provided with any data so we save it like this and we now want to do the same for the done complete event so I'm actually just going to for the sake of time copy this and this one transitions to complete okay so I think we've got our state machine decent right now but we haven't actually put things together into our react app so that's what's next so we'll come down here and the first thing we want to do is use the use machine hook from XD react and so use machine and we'll give it our machine which was the data machine and what it gives us back are a couple things the first one is something that typically is called current and that's sort of the current state of the machine that gives us access to what is the actual state it gives us access to the context etc and we also get a send function which allows us to send events to our state machine from inside of react so once we have that we can access our data from the current context like that with our data we can map the data rather than mapping the empty array the next thing that we want to do is determine when to show this late this loading element we don't want to always show we're not always loading data so the way we can do that is we can ask if the current state matches loading so if this is true um show the loading so when do we want to show the load more button we want to show the load more button when the current state matches more cool save that so when current match is loading will show loading when it matches more will show the more button and the last thing we're missing is how do we handle actually sending the event to load more so we've an on-click handler here and what we do is we come into the function that's called when that occurs and we would use send and we would send the load event to our machine so keep track or in more and we're sending it the load event so if we come up and look at our state when we're in more we're listening for the load event and what should happen we should transition to the loading event so that would kick us up here to the loading state and as soon as we enter loading state we invoke this service which will load data from our data source and once it's loaded the data source it will trigger either the Dunmore or the done complete events those events will run some actions when it happens to basically take that new data and combine it with the existing data in our context and then update the context to match and that will cause react to re-render and we can show the new data so let's actually try this out whoo all right stay table of transitions is deprecated so maybe it's not musician it's too what did I do wrong oh I see it's not - or transition its target sorry for all of that confusion there we go okay so when we load this the initial state is loading so that's why it goes into loading right away it calls our service which loads the first ten elements from the array and because there's more to load it shows the more button we click this it's loading for a sec and then when it has that the data ready it displays it we load more again it's loading now it's here but we're not seeing the load more data anymore and that must mean we're no longer in the more state we're now actually in the complete state because we've loaded all the data that's available to us so just to review this again quickly we've created a data machine that has four states loading more complete and failure and then we're using a service to actually load our data and we're storing this data in the context we've injected this state machine into our react app using the user machine which gives us ability to access the current state of the machine and to send it to send it events so what's in current we have the contacts which is all of the data but we also have a function called matches which allows us to basically see which state we're currently in hope you enjoyed this video take care have a good day bye
Info
Channel: Leigh Halliday
Views: 8,715
Rating: 4.9753847 out of 5
Keywords: react, state machines, xstate
Id: XaHk9vhmus4
Channel Id: undefined
Length: 18min 54sec (1134 seconds)
Published: Mon Sep 30 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.