<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

Introdução

Introdução ao Vue.js

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

Componentes e props

Slots, emits e ciclo de vida

Introdução ao Nuxt.js

Criando o projeto Gumball Verse

Primeira requisição com useFetch

Rotas a partir de arquivos

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

Conclusão e próximos passos

</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.


Por que cai em 500 e não em 404?

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

A solução: createError

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,
    });
}

O Nuxt então exibe o nosso error.vue com o status correto.


Detalhes do personagem com tratamento de erro

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>