Here you can know better the Pokémons you like!
You can visit https://jpbast-pokedex.vercel.app/ for checking it on production
Make sure you are using Node version >=18.x
.
On your terminal, run:
yarn install
Then:
yarn dev
Finally, the app should be running at:
http://localhost:3000
For checking all the content within the app, you can visit the following pages:
- Home page (
/
) - Pokémon detail (
/:name
)
On the top of the page we have a search input where you can find a specific Pokémon by its name
or
id
. The search is only triggered if you hit Enter
or the Search
button. If the Pokémon exists,
it will be displayed below replacing the list. If it does not exist, a error message will be
displayed.
If you have searched for a Pokémon but want to display the list again, simply erase the input value or hit the Pokémon logo.
To improve performance, the list was implemented with Infinite Scroll
. Pokémons are loaded every
20 as you scroll through the page. For better user experience, a Skeleton
is displayed for each
card every time a request is ongoing. If you scrolls too much and decide to return to the top, just
hit the floating button on the bottom right.
To access detailed Pokémon info, just click on the card and you be sent to another page.
Here you can find a more detailed information about the Pokémon you want. The entire page's color scheme is dynamic and it depends on the Pokémon color type.
The entire page is responsive just like the Home page.
- React with Vite
- TypeScript
- TanStack Query
- Tailwind
- Ant Design
- Axios
- ESLint
- Prettier
In order to improve performance, user and development experience, I decided to go with TanStack Query. All requests are handled by the following custom hooks:
-
usePokemonList
: this hook gets all the Pokémon data needed on the home page and it's ready to use with infinite scroll. All the data needed is fetched here and then parsed to make it easier to consume through the components -
usePokemon
: used for building the detail page and for getting the result from the search input.
Cache and overall performance were the main concerns so both hooks were developed with it in mind.
usePokemon
has the same queryKey
used on the usePokemonList
, so the detail page is fully built
consuming the cache if it exists. The opposite might also happen: if you first visit Pikachu page,
for example, and then navigate to the list, Pikachu information will be pulled from the cache.
Navigation between pages is pretty fast since no new requests are made. Page refresh is also pretty fast since it pulls the data from cache if it exists.
In order to prevent unnecessary renders and requests, the search input was built using ref
. I've
added a state to display the single card and trigger the search request, but that's it.
The app router was built with React Router Dom.
Every error is handled by the Error Boundary
and the React Router Dom
. If an unexpected error or
a response error from the requests happens, a error page is displayed. This page has a button so you
can reload the app.
For not found pages I created another page component that is quite similar to the error page.
If a searched Pokémon is not found, this is the feedback you'll see
Most of the styles and components were made with Tailwind and Ant Design.
For the fonts, the whole app is consuming the Google Inter. For improving performance and avoiding
layout shift, I downloaded the .ttf
files inside the /assets
folder and loaded it from there.
Furthermore, every component and page is responsive.
For the animations, you can find it on the skeletons and the stats bar filling up on the detail page
The linting is being handled by ESLint and Prettier with some rules I usually set. I also added Husky for checking lint errors when I commit.
src/assets
: font files and Pokémons type iconssrc/components
: visual componentssrc/hooks
: custom hooks for managing the API requestssrc/layouts
: app containerssrc/pages
: all app pagessrc/router
: React Router Dom setupsrc/styles
: global stylessrc/typings
: most important types used multiple typessrc/utils
: utility functions and axios setup