Banner
Home / Blog / Suspense – new feature in Vue 3
Suspense – new feature in Vue 3

Suspense – new feature in Vue 3

Filip Rakowski
Filip Rakowski
November 20th 2019

Recently I wrote about new features available in Vue 3 where I briefly introduced what features we can expect in the next major release of Vue.js.

In today's article, I want to talk a little bit more about one of the most interesting ones - Suspense.

This article is based on active RFCs and analysis of vue-next repository. There is no guarantee that the features mentioned in this article will land in Vue 3 exactly in the described form (but most likely they will).

What is Suspense?

Suspense is a special component that renders a fallback content instead of your component until a condition is met. This condition is usually async operation happening in your components setup function. It’s a technique well-know from React ecosystem.

If that sound blurry to you don’t be scared. I will dig deeper into this shortly.

With Composition API, Vue 3 will introduce a setup method, which lets you hook into different component properties with functions like computed() or onMounted(). Properties returned by setup method are available in Vue template the same way data, methods, and computed properties from Vue 2 Options API are available right now.

<template>
  <div> 
    Clicked <b>{{ count }}</b> times. 
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
import { ref } from 'vue'

export default {
  setup () {
    const count = ref(0)
    function increment () {
      count.value++
    }    

    return { 
      count,
      increment
    }
}
</script>    

Sometimes you might want to perform async operations in setup method like fetching data from external APIs (similarly to what is currently done in created lifecycle hook.

export default {
  async setup () {
    const user = await fetchUser()
    return { user }    
  }
}

In that case, you probably don’t want to display your component until we've fetched the user data You probably also want to display some loading indicator while it’s being fetched. This is exactly what Suspense is made for!

If we wrap above component in Suspense it will display fallback content until the async operation in our component is resolved:

<Suspense>
  <template #default>
    <UserProfile />
  </template>
  <template #fallback>
    <div>Loading...</div>
  </template>
</Suspense>

Very elegant, isn’t it? We can also suspend component loading for multiple async components.

If we have another component that fetches funny cat images and put it along with UserProfile fallback content will be shown until both components will resolve their async operations:

<Suspense>
  <template #default>
    <UserProfile />
    <FunnyCats /> 
  </template>
  <template #fallback>
    <div>Loading...</div>
  </template>
</Suspense>

Error handling

So far, we've covered what happens when async operations are successfully resolved, but what happens if it fails and gets rejected?

Thankfully we can use the new ErrorCaptured lifecycle hook to catch errors like this and display a proper error message. Take a look at below example:

<template>
  <div v-if="error">
   {{ error }}
  </div>
  <Suspense v-else>
    <template #default>
      <UserProfile />
    </template>
    <template #fallback>
      <div>Loading...</div>
    </template>
  </Suspense>
</template>

<script>
import { onErrorCaptured } from 'vue'

setup () {
  const error = ref(null)
  onErrorCaptured(e => {
    error.value = e
    return true
  })}
  return { error }
</script>

In the above example, we display fallback content until the async operation in UserProfile is resolved. If something goes wrong and it’s rejected, we use onErrorCaptured Vue hook to capture the error, pass it to error property and display it in a template instead of fallback content.

Summary

Suspense is a very handy component that enables an easy and elegant way of displaying fallback content until async operations are performed. With ErrorCaptured lifecycle hook you can also gracefully handle errors that happened in a suspended component.

Start learning Vue.js for free

Filip Rakowski
Filip Rakowski
Co-founder & CTO of Vue Storefront - Open Source eCommerce Platform for developers. I'm passionate about sharing my knowledge and thoughts on software architecture, web performance, Vue and raising awaraness about business impact of the technology and code we write. When I'm not working I'm probably playing with one of my cats.

Latest Vue School Articles

Crafting a Custom Component Library with Vue and Daisy UI

Crafting a Custom Component Library with Vue and Daisy UI

Do you want to build your own component library with Vue.js? We’ll show you how to get started in our course: Crafting a Custom Component Library with Vue and Daisy UI.
Daniel Kelly
Daniel Kelly
What Makes a Good (Vue) Component Library? A Checklist

What Makes a Good (Vue) Component Library? A Checklist

Considering building a Vue Component library? Checkout this checklist of concerns you should make sure to remember!
Daniel Kelly
Daniel Kelly

Our goal is to be the number one source of Vue.js knowledge for all skill levels. We offer the knowledge of our industry leaders through awesome video courses for a ridiculously low price.

More than 120.000 users have already joined us. You are welcome too!

Follow us on Social

© All rights reserved. Made with ❤️ by BitterBrains, Inc.