Reacting to Param Changes — Transcript

Transcript of the free Vue.js lesson Reacting to Param Changeswatch the video lesson.

In this lesson, I want to cover an important caveat when it comes to params. When the user navigates from destination slash one slash Brazil to destination slash two slash Panama, the same component instance will be reused Since both routes render the same component, this is more efficient than destroying the old instance and then creating a new one. However, this prevents the component's lifecycle hooks from being retriggered. Most real-life applications don't store their data in local JSON files, but rather in some database somewhere, or some third-party service accessed via a REST API, a GraphQL API, or the like.

Getting data from such sources is always an asynchronous process, unlike importing the JSON file. Thus, it is common to make an AJAX request in the created lifecycle hook to fetch that data and then set the data to a component data property. This practice is directly affected by the reuse of the component instance between route changes. So how do we resolve such an issue?

First, let's recreate the issue. I've created a simple dummy API to fetch the data via AJAX that we have stored in the JSON file already. app and provide the slug for whichever destination we want the data for. So let's make an AJAX request to the API using JavaScript's fetch function in the created at hook.

If you're not familiar with the fetch function, you can read more about it in the MDN docs provided in the description below. I'll use the async await syntax so that I can wait for the promise returned by fetch to resolve. Finally, I'll set the destination to the response from the API. Notice that destinations won't be a computed property anymore as we're setting it directly.

Let's remove the computed property. And now we need to initialize the data property to null. Now, if we visit the site in the browser, you'll see that we still get our page content, but it's just a little delayed. That's because of the async nature of the data now.

It's not available as soon as the page loads, but only after the AJAX request is finished. We've also got an error in the console. cannot read property name of null. This is because for that split second that the destination is null, the template can't access the name property on null.

Let's just add a vif to our wrapper tag to make sure destination is available before trying to render the page. Awesome. Normally, at this point, you'd probably want to add a loading indicator. But for our purposes, this is working great.

However, look what happens when we try to navigate to an alternate destination. Oh no, the route changes in the URL, but the page content does not. This is a direct result of the created hook not being rerun as we switch pages. The first solution for remedying this issue is to watch the route params and rerun the AJAX request when they change.

dollar sign watch. pass it a function that returns what we want to watch for changes. And for the second argument, provide a callback function that runs the AJAX request. I'll just copy and paste the Ajax request from above.

Now, over in the browser, navigating between the destinations works as expected. However, we do have some duplicated code in the created hook. We can fix that by extracting it to a method. We'll call the method initData.

Then we'll copy and paste the AJAX request. Make our function asynchronous. And then we'll use the method both as the callback method for watch and directly in the created hook. Nice, that's cleaner.

and it still works. The advantage of this approach is that we still get the performance benefits of not having to completely recreate the component from scratch between pages. However, this performance boost is negligible for our page components. Besides that, calling dollar sign watch every time you have a page component that fetches data can be a mental burden that must be remembered every time.

Therefore, I only suggest using this approach when your application has a limited number of pages that fetch data in one of the Vue lifecycle hooks, or if your application is suffering from performance issues when navigating between pages. So what's our other option? The alternative solution is to force Vue to recreate the page component on every page change. Let's remove the watch so that we can use this alternative approach.

To understand the following approach, it's important to understand View's key attribute. View has a special component attribute called key that is used by View under the hood to optimize performance. It does this by getting some knowledgeable developer input about what needs to be re-rendered and when. Whenever the value of this key attribute changes, Vue will destroy the currently rendered component that the key is applied to and then re-render it from scratch.

path. This works because the path is always going to be something different for each page. As you can see, this approach provides the same outcome as using dollar sign watch. The downside is that it does take a little more JavaScript computation between each page change as the component is completely destroyed and rerendered.

But it's not even really noticeable for our application. The upside is that this solution is one and done. I don't have to think about it at all as I'm creating other page components. I can just make my AJAX requests in the created hook and go about my merry way.

Therefore, I suggest using this approach most of the time. For simplicity's sake, let's go ahead and revert the application to using the data from the JSON file. We'll remove the created hooks and the methods option. We'll also remove the destination data property.

And then we'll add back in the computed property. Great, we're back to using the JSON data and the page still works as expected. Route params are a powerful tool, essential in any application. Just be sure to take extra care when navigating between pages that share the same page component and be aware that you might need to take some extra steps to ensure your data is updated properly.