Practice writing queries with React Query and displaying loading states, error states, and data. We will be using the Pokémon API.
-
Clone this repo, navigate to it, install packages, and start the server with
npm run dev
Tip
cd query-em-all npm i npm run dev
client/apis/pokemon.ts
is written for you! Take a look at it and then try it out in Thunder Client (a VS Code extension for testing APIs) to see what it returns. The types are also written for you in models/pokemon.ts
, they only contain the fields we are interested in.
<AppLayout>
is rendering two client-side routes, /
and /pokemon/:name
:
/
renders<PokemonList>
, a list of hardcoded Pokémon/pokemon/:name
renders<PokemonDetail>
, a single Pokémon (with lots more information), also hardcoded
Visit localhost:5173/ and localhost:5173/pokemon/bulbasaur, Bulbasaur is currently our only resident Pokémon. We will be replacing the hardcoded data with data from the API.
- Install React Query and React Query Devtools
npm i -D @tanstack/react-query @tanstack/react-query-devtools
-
In
client/index.tsx
import{ QueryClient, QueryClientProvider }
from@tanstack/react-query
-
In
client/index.tsx
import{ ReactQueryDevtools }
from@tanstack/react-query-devtools
-
Create a new
QueryClient
instance and wrap the<RouterProvider />
component in a<QueryClientProvider>
component, passing theQueryClient
instance as a prop -
Within the
QueryClient
instance, add in the<ReactQueryDevtools />
component.Tip
// creating a new QueryClient instance const queryClient = new QueryClient() // ... root.render( // wrapping the app in a QueryClientProvider // and passing the QueryClient instance as a prop // Adding ReactQueryDevtools <QueryClientProvider client={queryClient}> <RouterProvider router={router} /> <ReactQueryDevtools /> </QueryClientProvider> )
-
As a user, I want to see a list of the first generation of Pokémon so that I can see what Pokémon there are
-
In
<PokemonList>
useuseQuery
andfetchPokemonGeneration
to render a list of Pokémon (just the names)More about fetching Pokémon
fetchPokemonGeneration
takes ageneration
parameter, which is a number between 1 and 9, in this case, we want to fetch the first generation of Pokémon, so we can pass1
- Check out
interface PokemonGeneration
inmodels/pokemon.ts
useQuery
takes a key (a string) and a function that returns a promise (fetchPokemonGeneration
, in this case) and returns an object with adata
property, which will eventually contain data returned by the promise
Read more about keys and queries in the React Query docs.
-
- As a user, I want to see a loading state while the list of Pokémon is being fetched so that I know something is happening
More about loading states
useQuery
returns anisPending
property that you can use to determine when to render a loading state- You can use the
<LoadingSpinner>
component to render a special pokéball loading spinner
-
As a user, if something goes wrong while fetching the list of Pokémon, I want to see an error state so that I know something went wrong
More about error states
useQuery
returns anisError
(true or false), anderror
properties that you can use to render an error state
-
As a user, when I click on a Pokémon in the list, I want to see more information about that Pokémon so that I can learn more about it
- In
<PokemonList>
, add a<Link>
to each Pokémon that links to/pokemon/:name
, where:name
is the name of the Pokémon, note: the URL should be the lowercase name of the Pokémon (e.g./pokemon/bulbasaur
) - In
<PokemonDetail>
, useuseQuery
andfetchPokemonByName
to render the Pokémon's name, image, and types
More about Pokémon details
Have a look in
models/pokemon.ts
at thePokemon
type to see what properties are available to you.- In
<PokemonDetail>
, add loading and error states
- In
- As a user, I want to see more information about the Pokémon so that I can learn more about it
- In
<PokemonDetail>
, useconsole.log
to see what the actual API is returning - Choose some fields and add them to the
Pokemon
type inmodels/pokemon.ts
- In
<PokemonDetail>
, render those new fields in some way of your choosing
- In
More about stretch challenges
-
As a user, on the homepage (
/
) I want to see a list of all the generations, so that I can click on one, go to/generations/:generationId
and see the list of Pokémon for that generation -
As a user, I want to see a search bar at the top of the page, so that I can search for a Pokémon by name, when I hit enter, I want to be taken to
/search?name=pokemonName
, which should display a filtered list of Pokémon
This challenge can be used for the following trello assessment(s):
- WD02: Build a Javascript application that consumes a restful JSON API