Replacing Reactive State the Wrong Way — Transcript

Transcript of the free Vue.js lesson Replacing Reactive State the Wrong Waywatch the video lesson.

The mistake I want to show you in this lesson is a very tricky one, and it can wreak havoc on your code base, causing all kinds of different bugs if you aren't aware of what's going on. So let's get into it. Here inside of my code base, I've coded up something that's a pretty common scenario. Over on the right-hand side, you can see the result.

We have a list of posts. These are coming from an API. And then at the bottom, we have controls in order to move through different pages of posts. Cool.

Over in the code editor, how is this working? Well, I have the page set, first of all, as a reactive ref. This keeps up with what page of posts we're currently on. There is a per page reactive ref, which tells my API how many per page I want it to send back.

It doesn't necessarily have to be a reactive ref because we never change it. I just did it for consistency here. And then finally, we have a post variable. It's an empty array by default.

And this is where we'll end up storing the posts once they're fetched. On line ten, I'm extracting a get post function from a use dummy JSON composable. The implementation here is not important. What is important is that getPost makes an API request, which we call inside of this fetchPost function down here.

We pass it how many per page we want and which page we currently are looking for. And that returns the fetched post from the API. value equal to the result from the API request. Awesome.

Now, this is a function that hasn't actually been called yet. It's just defined. So on line sixteen, we call it on page load and then we call it again here on line seventeen whenever the page changes. And this works absolutely great.

You saw it working over on the right hand side. So what's the issue? Well, the issue is that some people prefer to use the reactive function instead of the ref function. value would become just post equals fetched post.

As soon as I hit Save, though, you'll notice over on the right-hand side that my page is broken. The posts are no longer displayed. So this is a limitation of the reactive function. Yes, we are using an array for the initial value, so it is the proper type of data.

However, down here on line-thirteen, when we're setting all the new posts into the array, we're completely overriding that reactive object. And so Vue can no longer track the changes and re-render the template. We could get around this by somehow looping over the fetch post and pushing each one in individually, but that's kind of gross. I would rather just set the whole thing.

So that's why ref works perfect for this. So if you don't watch any further, the takeaway here is whenever you want to replace the entirety of a reactive variable, you always want to use ref. And that will work just fine. However, I want to go down this rabbit hole a little bit deeper because this can get super, super tricky and hide some very interesting bugs.

What do I mean by that? Well, let me take it back to reactive real quick. And yes, the page is broken. It's very apparent that the page is broken now.

But what if inside of my fetch post function, I was also updating some other piece of reactive data? I don't know necessarily what it would be for this particular page, but let's just for something. OK, I'm going to create a piece of reactive data called counter. And it will have a initial value of zero.

Then down inside my template, I'll render the counter. Lastly, whenever we fetch posts, let me automatically increment that counter. Okay, great. So now you'll notice that even though we use reactive to declare posts, we do have the first page actually displaying post as it ought to.

If I click next to go to page two, that indeed works as well. So what is going on here? Does using reactive and completely replacing that reactive variables value work or does it not? Well, it still does not.

However, we do get the visual that we expect because something else has changed. Some other reactive variable has changed, triggering the rerender. You can see now how this could be a very tricky issue then to catch. At this point, everything looks like it's working fine, but let's say now we wanted to watch our posts for changes.

and then perform some side effect. Of course, we do need to provide the deep option as you learned in the last lesson, since we are working with an array. Now over in the browser, I'll click through a couple of different pages here in order to try to trigger our watcher. Now let's inspect the console.

And oh no, there is nothing logged here. That's because even though the page is re-rendering correctly, posts is no longer reactive. And so watching it does nothing at all. Furthermore, if we were to create a computed prop based on posts, that wouldn't work either.

Whoops. I need to import computed here. And yeah, now the number of posts is always stuck at zero. So what is the solution?

Well, the easy thing to do is just to make sure you're always using ref when you want to replace the complete value. My honest suggestion is you should really just be using ref everywhere and leave the reactive function in the dust.