<aside> <img src="/icons/arrow-northeast_gray.svg" alt="/icons/arrow-northeast_gray.svg" width="40px" />
Índice
</aside>
<aside> <img src="/icons/notion_green.svg" alt="/icons/notion_green.svg" width="40px" />
Conteúdos
Anatomia de um componente .vue
Interpolação e reatividade com ref e computed
Diretivas: v-bind, v-on, v-if, v-for e v-model
Criando o projeto Gumball Verse
Primeira requisição com useFetch
Layout, base do projeto e nuxt.config.ts
Consumindo a API nas listagens
Páginas de detalhes com rotas dinâmicas
Tratando o erro 404 com createError
Títulos das páginas com useHead
Filtros, paginação e busca com debounce
Desafio: título e favicon dinâmicos
</aside>
Na página anterior, vimos que acessar um personagem que não existe quebra a página com um erro 500. Nesta página vamos entender por que isso acontece e como mostrar o erro 404 corretamente, usando o createError.
Hoje, quando a API responde que o personagem não existe, o data fica vazio. Mesmo assim, o template tenta ler data.name, e ler uma propriedade de algo vazio gera um erro de JavaScript. O Nuxt entende isso como uma falha no servidor e mostra um erro 500 genérico, como se o servidor tivesse quebrado.
O mesmo acontece em /locations/:id. O problema é que, para quem acessa, a informação correta é outra: a página não existe, ou seja, um erro 404.
| Status | Significado |
|---|---|
| 404 (Not Found) | O recurso procurado não existe |
| 500 (Internal Server Error) | Algo quebrou no servidor |
| 503 (Service Unavailable) | O serviço está indisponível no momento |
Para mostrar o erro correto, basta tratar esse caso logo depois do useFetch, verificando se houve erro ou se o data veio vazio, e lançar o erro certo com createError:
if (error.value || !data.value) {
throw createError({
status: error.value?.status === 404 ? 404 : 503,
fatal: true,
});
}
if se a requisição falhou ou se não veio nenhum dado;data.name de algo vazio.O Nuxt então exibe o nosso error.vue com o status correto.
Atualize o arquivo app/pages/characters/[id].vue:
<script setup>
const route = useRoute();
const { id } = route.params;
const { data, error } = await useFetch(`https://gumball-api-server.vercel.app/characters/${id}`);
if (error.value || !data.value) {
throw createError({
status: error.value?.status === 404 ? 404 : 503,
fatal: true,
});
}
</script>
<template>
<section class="section section--details">
<div class="container">
<BackLink to="/characters">Todos os personagens</BackLink>
<CharacterDetails
:name="data.name"
:full-name="data.fullName"
:image="data.image"
:description="data.description"
:role="
data.role === 'main'
? 'Principal'
: data.role === 'minor'
? 'Secundário'
: 'Coadjuvante'
"
:status="
data.status === 'alive'
? 'Vivo'
: data.status === 'deceased'
? 'Morto'
: 'Morto-vivo'
"
:species="data.species"
:gender="data.gender"
:age="data.age ? `${data.age} anos` : 'Desconhecida'"
:occupation="data.occupation"
:animation-style="data.animationStyle"
:first-appearance-code="data.firstAppearance?.code"
:first-appearance-title="data.firstAppearance?.title"
:aliases="data.aliases"
:voice-actors="data.voiceActors"
:colors="data.colors"
:color="getCharacterColor(data.colors)"
/>
</div>
</section>
</template>