Suspense - uma nova feature no Vue3
Tags: suspense, javascript, vue
Published: 2020-02-03 19:48:23

Fala galera, esta é mais uma tradução livre de um artigo do pessoal do [Vueschool](https://vueschool.io/articles/), dessa vez sobre uma outra feature do Vue 3, que é o componente `Suspense`. Não deixe de conferir!

[Link do post original](https://vueschool.io/articles/vuejs-tutorials/suspense-new-feature-in-vue-3/) escrito pelo [Filip Rakowski](https://twitter.com/filrakowski).

---

Recentemente eu escrevi um artigo sobre [as novas features disponíveis no Vue 3](https://vueschool.io/articles/vuejs-tutorials/exciting-new-features-in-vue-3/) ([texto também traduzido](https://dev.to/codecasts/conheca-as-novas-funcionalidades-do-vue-3-o2g)) onde eu brevemente introduzi quais features podemos esperar na próxima major release do Vue.js.

No artigo de hoje, eu quero falar um pouco mais sobre uma das mais interessantes - Suspense.

Este artigo é baseado no repositório vue-next. Não há garantia de que os recursos mencionados neste artigo cheguem ao Vue 3 exatamente da forma descrita (mas é provável que aconteça).

## O que é o Suspense?

Suspense é um componente especial que renderiza um conteúdo de *fallback* em vez do seu componente até que uma condição seja atendida. Essa condição geralmente é uma operação assíncrona acontecendo na função `setup` de seus componentes. Esta é uma técnica [bem conhecida do ecossistema React](https://pl.reactjs.org/docs/concurrent-mode-reference.html#suspense).

Se isso parece estranho para você, não se assuste. Eu vou me aprofundar nisso brevemente.

Com a *Composition API*, Vue 3 irá introduzir um método `setup`, que permite conectar diferentes propriedades de componentes com funções como `computed()` ou `onMounted()`. Propriedades retornadas pelo método `setup` estarão disponíveis no template Vue da mesma forma que `data`, `methods`, e `computeds` da *Options API* do Vue 2 são disponíveis agora.

```html
<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> 
```

Às vezes você quer realizar uma operação assíncrona no método `setup` como uma requisição de dados para uma API externa (similarmente ao se faz atualmente no método `created`).

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

Neste caso, você provavelmente não quer visualizar seu componente enquanto se está buscando os dados do usuário. Você provavelmente quer visualizar algum indicador de *loading* enquanto se está sendo buscado os dados. É exatamente para isso que o `Suspense` foi feito!

Se nós encapsulamos o componente abaixo em um `Suspense`, ele irá mostrar uma conteúdo de *fallback* enquanto a operação assíncrona do seu componente é resolvida.

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

Muito elegante, não? Também podemos suspender o carregamento para vários componentes assíncronos.

Se tivermos outro componente que busca imagens engraçadas de gatos e o coloca junto com o componente `UserProfile`, o conteúdo de *fallback* será mostrado até que ambos os componentes resolvam suas operações assíncronas:

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

## Manipulação de erros

Até agora, cobrimos o que acontece quando as operações assíncronas são resolvidas com êxito, mas o que acontece se elas falharem e forem rejeitadas?

Felizmente, podemos usar o novo *hook* de ciclo de vida `ErrorCaptured` para capturar erros como esse e exibir uma mensagem de erro adequada. Veja o exemplo abaixo:

```html
<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>
```

No exemplo acima, nós visualizamos um conteúdo de *fallback* até que a operação assíncrona em `UserProfile` seja resolvida. Se algo acontece de errado e ela é rejeitada, nós usamos o *hook* `onErrorCaptured` do Vue para capturar o erro e passá-lo para uma propriedade `error` e visualizá-la ao invés do nosso conteúdo de *fallback*.

## Resumo

`Suspense` é um componente muito acessível que disponibiliza uma maneira fácil e elegante de visualizar um conteúdo de *fallback* enquanto operações assíncronas são executadas. Com o *hook* de ciclo de vida `ErrorCaptured` você também pode graciosamente manipular os erros que acontecem no seu componente "suspendido".

---

Bom, mais uma tradução finalizada. Espero que tenha gostado. Não deixe de compartilhar este post para que mais pessoas sejam alcançadas por este conhecimento.

Até a próxima!