This episode is for members only

Sign up to access "Building Reactive Realtime Applications with Livewire" right now.

Get started
Already a member? Sign in to continue
09. Refactoring reactivity


Okay, so I'm now going to demonstrate the dangers of just blindly using that reactive attribute
within your Livewire components. To demonstrate this, let's go ahead and clear out what we have in our database first of all, and then we're going to come over and open up our post seeder, and I'm going to actually do this to subtract today, so we can continue to add records onto the end of this, and I'm going to generate this out with 1000 records. So let's go over and just
run our seeder again, so php artisan db seed post seeder, and if we head over to the browser, sure enough, we have got quite a few records in here. Now before we start to scroll down the page, let's just remind ourselves about what we did earlier to fix our reactivity issue, when we render them new chunks, we don't see the post IDs, or when we push to them,
we don't see them. So if we come over to our post chunk component, we know that with the IDs, we want these to re-render this component when they change, and we added reactive to solve that. Now if we head over, if we think about the way that we're doing this, we are technically adding in a reactive property within a loop, so we're effectively looping through each of these chunks,
and going ahead and outputting each of the chunks on the page. So let's go ahead and open up our network tab, make sure we filter by XHR request, go ahead and refresh the page, and just start to scroll. Now we saw earlier that we get a performance improvement when we chunk things like this, but actually now we're using that reactive property within this loop, we're going to run into an issue.
So I'm just going to keep scrolling down, keep an eye on the time of the request that this takes on the side. So I'm going to keep going down here, all the way to the end, this is why we did a huge bunch of records, and let's finish it up just about there. So I'm going to scroll down, and you can see that we're now getting into about 100 milliseconds per request. This is only going to increase when we
add more markup to each of our individual posts. So what is happening here? Well let's go ahead and open up one of these last ones. We know that we've got quite a few IDs in here, that's not necessarily the issue, but what's actually happening now is because we have a reactive property within a loop, this is re-rendering every single time. So we've got all of these components inside of here, we've
got the new post, but this is adding way too much markup every single time, and it's just slowing things down. So we need to think really carefully when we're doing something like this with infinite scroll, which is why we implemented infinite scroll in this course, so we could demonstrate this problem, and we need to find a new solution. Now there's nothing wrong with using a reactive
property, the example we looked at at the start of the course where we just had that very simple count isn't going to make much difference, but you don't want to iterate over a load of nested components and have them each have a reactive property. We're going to run into a huge amount of problems. So I'm going to go ahead and get rid of the reactive property, in fact I'll just comment
that out just to remind ourselves that that's where it was, and if I give this a refresh it's going to work, it's going to be quick, so if we just open up our network tab again and keep scrolling we're not going to see the same issue here. So let's just keep going down all the way down the page, you can already feel it's a little bit faster, and if we just go down here you can see
that we're not getting that continual increase in speed or in the time it takes for this request to make. But now that this isn't reactive, what that means is whether it's real time or not, when we go ahead and post something it's just not going to appear until we refresh the page. So in this instance, in this particular instance where we are loading more data in and we don't want this
reactive property in a loop, how do we get around this? Well this comes at a kind of trade-off. So at the moment, again let's go back to the browser and open up our network tab again, at the moment when we post something in here we make a couple of requests. So we make one to go ahead and post this, and then another one to go ahead and update the list. And that's not too bad,
but when we implement the solution we're about to implement now, we're going to end up with three requests. So three total network requests for when we post this. So that might not be ideal, but we're not going to see that continual speed increase. So there's a kind of trade-off here between the time it takes for each request and the amount of network requests you make.
You can improve this, but let's go ahead and implement this solution. And I think this is so much better to have three small network requests. It's not as bad as having a continuously increasing speed problem when we're working with network requests. Okay, so let's go ahead and figure this problem out. So we've got rid of the reactive property. What we want to do when this
post gets created, we still want to push to this overall chunks because we want to keep an eye on that. But now what we're going to do is target the individual chunk and push to that within its own component within an event listener. And that will just re-render that individual chunk, and that's what we want. So we're going to go ahead and dispatch out a method here, and that's what's
going to, when we pick this up in our individual chunk, create that additional network request. We're going to push to the first chunk. So we're going to give this a name with the index of the chunk. So when we create a post, we want to go ahead and push to the first chunk. So I'm going to say chunk zero. The reason we do that is in the individual chunks, when we listen for this event,
we want to listen to only within that chunk. So we're going to just call this prepend, and we're going to go ahead and put the post ID in there. So now what we can do is we can pick this event up dynamically using a dynamic value within our event listener inside of the post chunk component. So let's go ahead and create this out. So we'll create a method out in here called prepend to
chunk or whatever you want it to be called. We know that we are getting a post ID into here, and we'll do something in here in a minute. Now what we don't want to do, the whole idea of this is we don't want to say chunk prepend and then just listen to this on every chunk. We need this to be dynamic. So we actually need to accept in the chunk index for this particular chunk. So I
think we already passed that in a little bit earlier. Let's just go and have a look over in our post index here. And yeah, we passed this chunk in. So we know we can target the individual chunks with this event listener. So if we say on, what we can now do is say chunk dot, and then we can put a placeholder in here for the chunk we're listening to, and then prepend. And then only this
component will listen to that based on the chunk we get. So when we prepend, the chunk is going to be zero, and this will only listen to that chunk. So in here, we just want to go ahead and set the IDs to pretty much the same thing as we did before. So post ID, and then we want to spread out the IDs that we get inside of there. So let's just recap before we look at this. If we go over to our post
index, this is now no longer going to filter down into them child components, because we got rid of that reactive attribute. But now what we're doing is we're specifically telling this chunk to update itself over here. And that is then going to trigger a rerender, but just for the chunk that we are targeting. So let's go ahead and try this out. So I'm going to come over here. And yeah, so what
did I put in here? Check, that needs to be chunk. And let's give that a refresh. Okay, so I'm going to write hello in here, hit post. And there we go, that is working. Let's check out network tab out just so we can see what's going on here. Again, this isn't ideal, because we're sending quite a few network requests here, because we're dispatching these events and listening, and then a couple of
rerenders are happening. But if I do type a message in here and hit post, let's have a look. So we've got three network requests, but these are all pretty small. They're not rerendering the entire list, which is exactly what we want, because we want this to be fast. But we are making an additional network request. So let's go over to this. And you can see it's just basically updating
what we need. And when we don't have an issue here. But of course, now we can scroll. And although we are rerendering each of these chunks out, as we get to them, we don't have that sort of infinite increase in the time it takes for each of these to do. So the goal here was to make this fast, not necessarily limit the network requests. That is a trade-off. But I'm sure you'll agree,
having a few extra requests or a couple of extra requests, rather than being these really, really slow requests, I think is a good solution. We can always improve this later. But we want to, as we go, make sure that this is as fast as we can get it. So the last thing that we're going to do is just do exactly the same thing with prepending to chunk to deleting. Because at the moment,
if I go down here, and I delete something, again, it does get removed from the database. But we're not rerendering the list, we need to do exactly the same thing and come up with the same solution for deleting. So let's go over to our post index. And we're going to do this. But we're going to do that when we delete a post as well. So let's go ahead and paste this in here. And we're going to
say chunk delete. But we need to dynamically now target the chunk that we're deleting from, from within here. Now we know that is the index of the chunk that we're iterating through. So we can just append on here, the index. And then this now is the key, because remember, that's the position that we want to delete from. So it's the position within the chunk that we want to delete
from. So we're going to do this before unset, because obviously, we don't want to get rid of it before we actually dispatch this. And then we can implement this in side of post chunk to go ahead and delete this out of the list. So again, the same handler here, but we're going to say delete from chunk. And then in here, we're going to swap this out for an unset. And we're just
going to remove that from the IDs based on the key that we get through the position that we get through. So this now is our key or our index, whatever you want to call it, I'm actually going to switch over to index. Okay, so let's recap just specifically for this, go ahead and listen for that dynamic event that we're dispatching through from our component based on the index, this will
only listen from the chunk that we need to delete from past the key, which is the index of the item or the ID within that chunk, and then just go ahead and delete it from here. So this should work. Now, let's head over and just try this out. And it doesn't look like it's working just because we didn't change the event name over. So let's make sure that those match and we're all good.
Okay, so I'm going to hit delete. And there we go, that's being deleted. And even if we were to delete this from all the way down here, it's still going to work because we are telling it which chunk to delete from. And more importantly, our network requests are fast, we have added an additional one. But the goal here is to keep this fast.
12 episodes1 hr 43 mins


Livewire can react and re-render anywhere you need it to. But what if we have a infinite scrolling timeline of user posted content with updates in realtime? With added reactivity, we need to be a bit more careful about performance.

Let’s build this together, making sure we keep things running smoothly along the way.

Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!


No comments, yet. Be the first to leave a comment.