Olá, estudante da Alura! Meu nome é Pedro Mello, sou instrutor aqui na Alura, e quero te dar as boas-vindas a mais um curso de React, onde nosso principal foco será abordar temas de performance e observabilidade em aplicações React.
Audiodescrição: Pedro se descreve como um homem branco, de cabelo curto e castanho-escuro, barba castanho-escura, e olhos castanho-escuros. Ele tem piercings no nariz, veste uma camisa preta, e está sentado em um ambiente iluminado por luz azul-escura. Ao fundo, há instrumentos, quadros na parede, e um móvel com prateleiras e enfeites.
Para este curso, preparamos uma série de conteúdos interessantes. Vamos começar aprendendo como tratar erros em aplicações JavaScript. Portanto, vamos abordar ErrorBoundary
e tratativas de erros em rotas que não existem na aplicação.
Também vamos construir nossa própria função de tratativa de erro, com um console de mensagens customizado, onde poderemos passar as mensagens e identificar a stack de onde vem o erro, para saber de qual componente, isto é, de qual local o erro origina.
Além disso, vamos conectar nossa aplicação a um serviço de observabilidade, para podermos, além do ambiente de desenvolvimento, ter acesso a essas informações em um ambiente produtivo, ou seja, nosso site estará disponível na web para acesso.
Não paramos por aqui: vamos aprender sobre as dashboards que esse serviço vai oferecer, entender quais são as métricas que elas vão retornar, e o quanto que elas podem ser úteis no nosso dia a dia.
Para fechar com chave de ouro, vamos aprender a criar uma GitHub Action para automatizar a geração de relatórios do Lighthouse quando formos fazer o merge (mesclagem) de alguma pull request na branch main
do nosso projeto.
São muitos conteúdos interessantes para estudar neste curso!
Para realizar este curso, será importante possuir um conhecimento prévio sobre React, TypeScript, funcionamento de hooks, e utilização do useContext()
para gerenciamento de estado interno na aplicação. Além disso, abordaremos alguns tópicos de Tailwind e um pouco sobre o ciclo de vida de componente.
Esperamos você no próximo vídeo. Este curso tem muito a agregar! Você poderá utilizar esse conhecimento não só nos seus projetos pessoais, mas também nos projetos de empresa e projetos freelances que fizer.
Te aguardamos na nossa primeira aula. Até lá!
Vamos começar a tratar os erros da nossa aplicação React?
Na tela, temos a página da ByteBooks, um projeto provavelmente já conhecido por você. Caso contrário, ByteBooks é o projeto de uma editora de livros, onde temos filtragem de livros, uma listagem para os livros, uma página de detalhes, uma sacola e uma finalização de pedido.
O problema é que a nossa aplicação, no momento, não tem nenhuma tratativa de erro. Sendo assim, se ocorrer algum problema durante a requisição para buscar a listagem de livros, no fechamento de pedido, ou caso a pessoa usuária acesse uma rota que não está mapeada e não exista na nossa aplicação, não temos nenhuma blindagem de erros para isso.
Dito isso, o objetivo da nossa aula será entender quais são os principais pontos que podemos atacar para colocar essas tratativas de erro, e começar a desenvolver algumas estratégias no código para termos componentes que vão funcionar como fallback tanto no caso dos erros genéricos, que podem ser erros de requisição, quanto no caso da pessoa usuária acessar uma rota inexistente na aplicação.
Vamos voltar ao código para entender como está o projeto no momento. Na página de catálogo, correspondente ao arquivo index.tsx
dentro do diretório "pages > Catalog", na linha 23, assim que a aplicação é carregada, é feita uma requisição.
index.tsx
("src > pages > Catalog"):
useEffect(() => {
fetchBooks();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
fetchBooks()
é uma função que vem dentro do hook useBooks()
, que nada mais é do que o contexto referente a livros da nossa aplicação.
Podemos acessar a função useBooks()
pela referência pressionando "Command", no caso no Mac, ou "Ctrl" no Windows, e clicando sobre ela no código. Seremos redirecionados para o arquivo books.tsx
.
books.tsx
:
const useBooks = () => {
const context = useContext(BooksContext);
if (!context) {
throw new Error('useBooks must be used within a BooksProvider');
}
return context;
};
Se subirmos um pouco nesse arquivo, a partir da linha 64, encontramos toda a lógica de implementação da função fetchBooks()
. Observe que a requisição que fazemos para o back-end, que retorna quais são os livros existentes, está dentro de um bloco de try…catch.
try {
const response: Book[] = await fetch(
'https://raw.githubusercontent.com/cicatriz-dev/bytebooks-assets/main/data.json'
).then((res) => res.json());
await sleep(1500);
setState({
books: response,
isLoading: false,
});
} catch (error) {
setState((prev) => ({
...prev,
isLoading: false,
}));
}
Tudo que está dentro do bloco try
, ele tentará executar. Caso ocorra algum erro, ele vem para o bloco catch
, que começa na linha 81. Por enquanto, ele recebe um error
como parâmetro da função, mas esse error
não é tratado. O máximo que ele faz é tirar o estado de loading (carregando) da tela.
Por exemplo: vamos passar uma URL inválida para a requisição na linha 72, salvar e voltar ao navegador. Ao recarregar, observamos que, no console de desenvolvimento, foram retornados alguns erros a nível de console de desenvolvedor, mas simplesmente foi removido o carregamento da tela.
Não foi informado para a pessoa usuária de uma forma amigável que houve um erro na requisição, que a URL é inválida, nenhuma informação do tipo. Esse é um dos tópicos que vamos abordar.
Outro ponto importante é sobre a navegação de rotas. Sabemos que uma das rotas existentes na nossa aplicação é a rota de livro. Se clicarmos em um livro na lista da página, vamos para uma rota específica (por exemplo: "localhost:5173/book/1"). Observe que, após o "localhost" e a porta da conexão, temos o "/book" e o ID do livro.
Se digitarmos no endereço da tela inicial ("localhost:5173"), sem nenhum parâmetro, o final "/alura" ("localhost:5173/alura"), será uma rota inexistente no nosso projeto.
Apesar disso, ele mostra um conteúdo de fundo branco, mas sem nada. Não é exibida para a pessoa usuária a informação de que essa é uma rota inválida. O que podemos fazer para tratar esse erro e começar a resolver alguns problemas do nosso projeto?
No caminho "src/routes", vamos abrir o arquivo de rotas (index.tsx
). Nesse arquivo, há um <Switch>
na linha 12 que mostra as nossas rotas como se fosse uma ordem cronológica de acesso.
index.tsx
("src > routes"):
<Switch>
<Route exact path='/' component={Catalog} />
<Route path='/book' component={BookDetail} />
<Route path='/order' component={Order} />
</Switch>
O /
, correspondente à página inicial, fica em primeiro. Note que passamos exact
como parâmetro de <Route>
, para caso a pessoa usuária acessar /
seguida de alguma coisa, não cair nessa rota. Portanto, o exact
serve para abrir a página de catálogo (Catalog
) apenas se for exatamente /
. Depois temos as demais rotas do projeto: /book
e /order
.
Se quisermos implementar uma rota genérica para a nossa aplicação, ou seja, uma rota que servirá para qualquer acesso diferente das rotas que já existem, faremos o seguinte:
- Vamos passar uma nova
<Route>
;- O
path
, que em vez de receber algum conteúdo, receberá um caractere coringa, que é o asterisco (*
). Ou seja, qualquer rota diferente das três que já existem cairá nessa condição;- Como
component
, colocaremos um texto (<h1>
) apenas para verificar se será renderizado em tela.
<Switch>
<Route exact path='/' component={Catalog} />
<Route path='/book' component={BookDetail} />
<Route path='/order' component={Order} />
<Route path='*' component={() => <h1>Não ha nada aqui.</h1>} />
</Switch>
Após salvar o arquivo de rotas, vamos voltar ao navegador e atualizar a página. No canto superior esquerdo, abaixo do logo da ByteBooks, temos o texto "Não há nada aqui".
Agora que vimos em funcionamento o <h1>
que definimos na nossa rota, aguardamos você no próximo vídeo para fazermos a implementação de um componente um pouco mais visual, que dará um feedback melhor para a pessoa usuária. Nos encontramos no próximo vídeo!
Neste vídeo, vamos criar nosso componente de forma mais elegante para a pessoa usuária. Afinal, apenas mostrar um texto "Não há nada aqui" sem um botão para retornar à página inicial, caso desejado, não é a melhor experiência possível para a pessoa usuária. Sendo assim, vamos voltar ao código.
Dentro da pasta "pages", vamos criar um novo arquivo ("New File…") chamado NotFound/index.tsx
. Dessa forma, é criada tanto a pasta "NotFound" quanto o arquivo index.tsx
para inserir código.
NotFound
Vamos iniciar nosso componente como uma const
chamada NotFound
, que receberá uma arrow function. No escopo dessa função, primeiramente, vamos importar nossa navegação. Para isso, digitamos const navigation
que receberá useHistory()
.
index.tsx
("src > pages > NotFound"):
import { useHistory } from 'react-router-dom';
const NotFound = () => {
const navigation = useHistory();
}
Essa função será utilizada para redirecionar a pessoa usuária quando ela clicar no botão. Então, ao clicar no botão que colocaremos na página, a pessoa será redirecionada para a página de catálogo, que é a página inicial do projeto.
Em seguida, vamos adicionar um return
e, entre parênteses, abrir uma <div>
que englobará nosso componente nesta página. Vamos adicionar como className
o valor flex1
, para preencher todo o espaço disponível na tela. Também definiremos que todo o conteúdo será flex
e estará dentro de um flex col
, ou seja, estará organizado em colunas.
Além disso, centralizaremos todos os itens (items-center
) e justificaremos eles ao centro da tela (justify-center
). Por fim, como já temos o header
da aplicação, com a logo da ByteBooks e a sacola, vamos dar uma margem de 16 pixels (mt-4
) para um espaçamento adequado entre os conteúdos.
// código omitido
const NotFound = () => {
const navigation = useHistory();
return (
<div className="flex-1 flex flex-col items-center justify-center mt-4">
</div>
)
}
Com a <div>
fechada, vamos adicionar um texto em <h2>
: "Oops! Não encontramos nada por aqui.". Dentro desse <h2>
, vamos passar um className
para que o texto receba algumas propriedades.
Esse texto será centralizado (text-center
), utilizará uma cor específica (text-[#002F52]
), e terá um tamanho de 32 pixels (text-[32px]
).
<div className="flex-1 flex flex-col items-center justify-center mt-4">
<h2 className='text-center text-[#002F52] text-[32px]'>
Oops! Não encontramos nada por aqui.
</h2>
</div>
Adicionaremos também uma imagem ao nosso projeto, a qual já temos e usamos na página de catálogo. Faremos isso logo abaixo de <h2>
, adicionando a tag <img>
.
Lembre-se de que as nossas imagens estão na pasta "public", então, ao gerar o estático do site para o server-side rendering ou para uma aplicação rodando apenas do lado do cliente, não precisamos fazer o caminho completo para importá-la. Podemos fazer o caminho relativo passando apenas a barra e o nome da imagem mais o formato dela.
Dito isso, o atributo src
será /not_found.webp
, que é o formato da imagem. Vamos passar uma mensagem alternativa (alt
) caso a imagem não carregue, ou seja usado um navegador que não suporte carregamento de imagem, o que é bastante raro hoje em dia.
Por fim, passaremos algumas propriedades de estilização para className
: passamos a largura (width
) como 50% (w-1/2
); a largura máxima (max-width
) de 500px (max-w-[500px]
); margem automática no eixo X (mx-auto
), portanto, alinhada ao centro; e uma margem ao topo de 16px (mt-4
).
<img src='/not_found.webp' alt='sem resultado' className='w-1/2 max-w-[500px] mx-auto mt-4' />
Para finalizar, teremos um botão com algumas classes e um evento de clique.
<button
className='py-3 w-1/4 bg-[#EB9B00] hover:opacity-80 rounded-md shadow-md'
onClick={() => {
navigation.push('/');
}}
>
<h3 className='text-white text-lg font-medium'>Voltar ao Inicio</h3>
</button>
Nesse botão, teremos um espaçamento interno (py-3
), uma largura de 25% em relação à tela (w-1/4
), um fundo laranja (bg-[#EB9B00]
), uma opacidade ao passar o cursor (hover:opacity-80
), um arredondamento das bordas (rounded-md
), e uma sombra para destacar (shadow-md
).
Além disso, há o evento de clique (onClick
), que usará o navigation
, importado na linha 4, para fazer a navegação até a página /
, ou seja, a página inicial do projeto.
Dentro desse botão, também adicionamos um texto <h3>
que foi "Voltar ao início". Passaremos para a tag <h3>
o atributo className
recebendo text-white
, text-lg
e font-medium
.
No final, podemos fazer um export default NotFound
.
Código final do arquivo
index.tsx
("src > pages > NotFound"):
import { useHistory } from 'react-router-dom';
const NotFound = () => {
const navigation = useHistory();
return (
<div className='flex-1 flex flex-col items-center justify-center mt-4'>
<h2 className='text-center text-[#002F52] text-[32px]'>
Oops! Não encontramos nada por aqui.
</h2>
<img src='/not_found.webp' alt='sem resultado' className='w-1/2 max-w-[500px] mx-auto mt-4' />
<button
className='py-3 w-1/4 bg-[#EB9B00] hover:opacity-80 rounded-md shadow-md'
onClick={() => {
navigation.push('/');
}}
>
<h3 className='text-white text-lg font-medium'>Voltar ao Inicio</h3>
</button>
</div>
);
};
export default NotFound;
Feito isso, podemos salvar o arquivo, e na tela de rotas ("src > routes > index.tsx
"), na linha 16, em vez de utilizar <h1>
, vamos trocar pelo novo componente que criamos.
index.tsx
("src > routes"):
<Route path='*' component={NotFound} />
Nessa etapa, deve ser feita também a importação do
NotFound
na linha 8:import NotFound from '../pages/NotFound';
De volta ao nosso navegador, ele já mostra a tela de tratamento de rotas, com a mensagem que definimos, a imagem, que é a mesma utilizada no catálogo caso não exista nenhum resultado buscado, e o botão que, ao ser clicado, retorna à tela inicial que é a de catálogo.
Qualquer rota que digitarmos após isso, se ela não existir, seremos redirecionados para a tela que acabamos de criar. Reforçando: de volta ao código, o caractere coringa fará toda a mágica para nós; se nenhuma das rotas definidas for acessada, vamos para a do componente NotFound
.
A ideia é utilizar esse componente como um fallback justamente para otimizar a experiência da pessoa usuária na nossa aplicação. Não queremos que a pessoa usuária acesse uma rota inexistente ou tenha qualquer tipo de erro relacionado à rota e fique sem uma informação sobre isso.
Dessa forma, tratamos os problemas de rotas inexistentes na aplicação. Agora vamos criar um componente chamado ErrorBoundary
para tratar diversos outros tipos de erro na nossa aplicação, como erros sobre requisição, por exemplo. Abordaremos isso e muito mais no próximo vídeo. Te esperamos lá!
O curso React Vite: monitorando aplicações com New Relic possui 120 minutos de vídeos, em um total de 39 atividades. Gostou? Conheça nossos outros cursos de React em Front-end, ou leia nossos artigos de Front-end.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.