Use Vue.js Suspense Component to Handle Async Dependencies — Transcript

Transcript of the free Vue.js lesson Use Vue.js Suspense Component to Handle Async Dependencieswatch the video lesson.

Currently, we are using self-executing anonymous functions. view, we're using this over here to fetch our data from the database. And it works great for us, but it looks kind of messy. And with this approach, if I wanted to handle the loading state for this function to maybe render a loading spanner until the function is resolved, I would need to do that in each page component.

So it would make more sense to me to just use a normal function. So maybe a function called get projects like so, and this function I can trigger here with await get projects, and it should fetch the data like this. Get rid of the console log. It's not needed anymore, and it looks nice.

But unfortunately, it won't work. If we go to the browser and then inspect, bring up the console, and navigate to the projects page, we will get this error. Setup function returned a promise, but no suspense boundary was found in the parent component tree. A component with async setup must be nested inside a suspense component.

And this error over here means that our page's component script setup is now returning a promise. It became an async dependency, which is not what Vue expects to render here in the router view or not just the router view. It doesn't expect that anywhere. It expects a fully resolved component so that it can immediately render it.

For this to work over here and be able to trigger asynchronous functions on the top level of the script setup, we must use a built-in component called suspense. So what is this suspense story? Okay, let's put everything aside and focus on suspense. In the script setup, let's quickly craft a view component.

I'll create a new variable. Let's say it's going to be called mock component and set its value to a helper function that is called define component. And this is a helper function from Vue to help us define Vue components. And you wouldn't need to reach out to it like this in the real world.

I'm just using it for demonstration. And it's also a good chance to tell you about it. Anyway, it accepts a callback. And it should return another callback that resolves to whatever this component template should render.

So let's say that this component should render a greeting. I'll define a new constant called greeting and set it to a rep with the default value of hello. And right here in the return, I can use the H function like we did before to create a paragraph tag with the text of that greeting. value.

And now if I use this mock component inside my template, like so, save and check the browser and do a hard refresh, it will work just fine and it will render the template, which is that greeting. But if this component had a top level awaited promise, maybe we are updating the greeting value from the database. I'll add async here and await for a new promise. So await new promise.

Resolve like this. Update the greeting variable ref value with the data that we got from the database. So hello from the database. And then resolve the promise.

So resolve true or anything. And what we just did, we transformed our mock component into an async dependency. With that, in the browser, check the console again. we got the same error.

So yeah, yeah, we know already that top level awaited asynchronous functions will not work in Vue. Now, let's get to the point. The solution for this problem is that we use that suspense component. So if I move that mock component inside a Suspense component, check the browser again, do a hard refresh, it will work.

Hello from the database and we're not getting any errors. We're just getting a warning or maybe a heads up that Suspense is an experimental feature and its API will likely change. But Suspense is way too valuable to ignore, so we will keep using it in our project. js itself internally, it's being used in different occasions.

So yeah, I'll use Suspense and adapt if any changes comes up in the future. And by the way, this is not all what Suspense can do. This suspense component has a slot that we can use, and it's called fallback. And whatever we pass in here, it's going to be passed to the fallback slot inside the suspense component, and it will render it when your asynchronous function is still loading.

So maybe we can load a span that says loading. And right now it will not show up by the way. So this loading will not show up. It's not even going to render for a friction of a second.

And that's because our promise here is resolved immediately. There is no delay. So let's intentionally delay it. Set timeout.

Let's delay it for one second and move the result here. So this promise will be resolved after one second. If we check the browser now, do a hard refresh, here is our loading. After one second, here is our text.

So the fallback slot is being replaced when the promise is resolved. And that is the story of the Suspense component. It allows to process top-level async functions in our components, and it renders them when the promises are resolved. But that leaves us with a question.

How can we use Suspense with Vue Router? After all, we need ViewRouter to render the page that corresponds with the current path. So how can we make them play nice together? We will answer that in the next video.