- 📄 Descrição
- ✔️ Tecnologias utilizadas
- 📖 Fontes e assets
- 🤔 Desafios e aprendizados
- 📁 Acesso ao projeto
- 🛠️ Rodando localmente
Uma pokedex com o auxilio da PokeApi (uma api gratuita que armazena dados de Pokemon).
Typescript
: a linguagem na qual a aplicação foi desenvolvida (é uma versão tipada doJavascript
);React
: biblioteca principal da aplicação, é responsavel pela renderização das paginas;Hooks
: durante o desenvolvimento, fiz uso de diversoshooks
, tanto dos que veem pré-instalados com oReact
(comouseState
euseEffect
), quanto os que eu mesmo criei com o auxilio destes (comouseApi
euseQuery
);Styled-Components
: biblioteca utilizada para estilizaão das páginas da aplicação;Axios
: biblioteca usada para fazer as requisições para a API;
PokeApi
: API gratuita de onde todos os dados apresentados são coletados;WikiMidia
: onde encontrei as imagens das medalhas de cada tipo de pokemon (que usei como base para a paleta de cores);
Nesta sessão estão registradas algumas dificuldades técnicas que tive no decorrer do desenvolvimento, bem como a forma que utilizei para solucioná-las.
⛵ Navegação entre páginas no Github Pages
Essa foi a primeira aplicação com navegação entre páginas com rotas que adicionei ao Github Pages, e não demorou para que surgissem comportamentos inesperados.
A primeira dificuldade foi observar que as páginas estavam todas em branco. Isso ocorreu pois era necessário adaptar a rota base de "/" para "/pokedex/", endereço onde o Gh Pages publicou a aplicação.
A segunda foi quando notei problemas ao acessar rotas diferentes da rota base da aplicação, por exemplo:
- Se eu navegasse da rota base ('/pokedex/') para a rota de visualização de pokemons ('/pokedex/pokemons/') pela interface, tudo funcionaria como esperado.
- Se tentasse recarregar a página nessa segunda rota ou acessar sua url diretamente, seria renderizada uma pagina do Gh Pages constando 'Erro 404, página não encontrada".
Após um pouco de pesquisa, descobri que isso ocorre porque o Gh Pages lida com "landind pages", e quando renderiza a rota ele busca o arquivo index.html
, que no caso não existe para todas as rotas.
Demorou um pouco para encontrar uma solução para este problema.Cheguei a cogitar deixar dessa forma, pois "é o comportamento normal da plataforma". Porém a ideia de alguem acessar a aplicação, ver tudo funcionando, para depois atualizar a página e se deparar com esse comportamento, me fez continuar buscando soluções.
Muitas das possíveis formas de solucionar o problema seriam inviáveis devido as limitações do Gh Pages. Por exemplo: rodar um servidor NodeJs, que garanta que que todas as rotas sejam "redirecionadas" pelo arquivo index.html
(não é possível pois o ambiente do Github só permite arquivos estáticos).
No final, solucionei de forma relativamente simples: alterei a estratégia de roteamento.
A biblioteca react-router-dom
(usada para navegação das rotas), possui um roteador diferente do "padrão" (BrowserRouter
), chamado HashRouter
. Neste roteador as rotas passam a ser relativas a um #
(por exemplo: '/pokedex/' passa a ser '/pokedex/#' e '/pokedex/pokemons' vira '/pokedex/#/pokemons'), este caracter é interpretado pelo navegador como se estivesse tentando ir para uma região da mesma página, e consequentemente ele ainda busca o arquivo index.html
da rota principal, permitindo acessar todas as rotas diretamente e recarregar a pagina sem problemas.
💻 Consumindo e mostrando dados.
- A aplicação faz uso de dois endpoints da PokeApi:
- /pokemon/:id : que retorna todas as informações associadas a um pokemon que possui o id referenciado, me referirei a este endpoind como details.
- /pokemon/ : retorna uma lista de nomes e id's de pokemons, iniciando no query offset (valor padrão igual a zero) e retornando uma quantia de itens igual ao query limit (valor padrão igual a vinte), vou me referir a este endpoint como list.
- A cor dos cards na pagina de listar pokemons depende do tipo do pokemon, informação obtida com o endpoint details.
- As imagens dos pokemons são obtidas no repositório sprites, onde são nomeadas pelo id de cada pokemon (tornando fácil encontrar suas url's).
Agora, sobre minhas estratégias e dificuldades:
De inicio eu havia tentado usar estes recursos da seguinte forma:
- Ao entrar na tela de listagem de pokemons, fazia uma requisição para o endpoint list, pedindo o nome de todos os pokemons cadastrados (offset=0 e limit=1126);
- Com a função .map, renderizar um componente Card para cada pokemon com os dados obtidos e a imagem encontrada com o id.
- Dentro do componente Card se fazia uma requisição para o endpoint details, alterando a cor de fundo da padrão para a cor que representa o tipo do pokemon.
Fazendo as coisas desta forma, me deparei com alguns problemas:
- A pagina se tornou extremamente pesada e lenta devido a quantidade de componentes renderizados;
- As imagens demoravam muito para carregar tambem devido a grande quantidade;
- A chamada por details em cada Card de forma individual aumentou muito a demora para que os mesmos obtivessem suas cores finais;
No geral, a pagina estava longe de ser fluida e sua performance deixando muito a desejar.
Pensando em uma forma de otimizar este fluxo, pensei na segunda estratégia;
Minha primeira ideia de otmização foi diminuir a quantia de dados que precisam ser carregados, então:
- Passei a chamar list para pegar apenas uma porção do total de pokemons na pagina.
- Mostrar as informações da mesma forma da estratégia anterior.
- Adicionar um sistema de paginação, para poder navegar para a próxima pagina, onde uma porção diferente dos dados seriam carregados.
Desta forma a pagina e seus componentes passaram a carregar de forma mais rapida, mas ainda podia-se perceber as imagens terminando de carregar e um delay para os Cards assumirem suas cores finais.
Para passar uma maior impressão de fluidez, tive a ideia de colocar um timer na pagina. Depois de list retornar os dados iniciais, a pagina continuaria mostrando a tela de carregamento por alguns instantes a mais, enquanto isso as imagens e dados dos Cards terminariam de carregar (ocultas com a propriedade "display: none;" do CSS), dando uma maior sensação de fluidez.
Com isso, meu problema inicial estava solucionado, mas acabei me deparando com outro. Na lista de funcionalidades que pretendia implementar, se encontram a possibilidade de filtrar os pokemons por tipo, e a possibilidade de pesquisar pokemons por nome (visualizando a melhor correspondencia). Ambas são funcionalidades que a PokeApi não traz suporte, então para implementa-las, seria necessário ter todas as informações disponiveis de forma simultanea.
Refletindo sobre como viabilisar estas funcionalidades, pensei na terceira estratégia.
A versão mais recente deste projeto pode ser encontrada online aqui.
Para rodar o projeto localmente deve-se primeiramente ter instalado o NodeJs, e o git.
Tendo ambos instalados, clone o repositório:
git clone https://github.com/JongaMatos/pokedex.git
Depois navegue até a pasta gerada e rode o seguinte comando:
npm install && npm start
E pronto, está rodando localmente.