Last active
October 16, 2022 13:29
-
-
Save gabrielmlinassi/5410b1b7c31bfbace22b42f1fa45ce89 to your computer and use it in GitHub Desktop.
Test SWR data transformations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from "react"; | |
import useSWR, { SWRConfig } from "swr"; | |
import { ErrorBoundary } from "react-error-boundary"; | |
import axios from "axios"; | |
// grab it with Swagger instead of manually write | |
interface PokemonDTO { | |
abilities: {}[]; | |
base_experience: number; | |
forms: {}[]; | |
game_indices: {}[]; | |
height: number; | |
held_items: {}[]; | |
id: number; | |
is_default: boolean; | |
location_area_encounters: string; | |
moves: {}[]; | |
name: string; | |
order: number; | |
past_types: {}[]; | |
species: {}[]; | |
sprites: {}[]; | |
stats: {}[]; | |
types: { | |
slot: number; | |
type: { | |
name: string; | |
url: string; | |
}; | |
}[]; | |
weight: number; | |
} | |
interface Pokemon { | |
id: number; | |
name: string; | |
height: number; | |
types: { id: number; name: string }[]; | |
} | |
export const getIdFromUrl = (url: string) => { | |
const splitted = url.split("/"); | |
const id = +splitted[splitted.length - 2]; | |
return id; | |
}; | |
async function fetcher(path: string) { | |
return await axios.get(`https://pokeapi.co/api/v2${path}`).then((d) => d.data); | |
} | |
async function pokemonFetcher(path: string) { | |
const data: PokemonDTO = await fetcher(path); | |
// transform data | |
const pokemon: Pokemon = { | |
id: data.id, | |
name: data.name, | |
height: data.height, | |
types: data.types.map((type) => ({ | |
id: getIdFromUrl(type.type.url), | |
name: type.type.name, | |
})), | |
}; | |
return pokemon; | |
} | |
function usePokemon(id?: number) { | |
const { data, error } = useSWR(id ? `/pokemon/${id}` : null, pokemonFetcher); | |
return { | |
pokemon: data, | |
error, | |
isLoading: !data && !error, | |
}; | |
} | |
function ErrorFallback({ error, resetErrorBoundary }) { | |
return ( | |
<div role="alert"> | |
<p>Something went wrong:</p> | |
<pre>{error.message}</pre> | |
<button onClick={resetErrorBoundary}>Try again</button> | |
</div> | |
); | |
} | |
function HomePage() { | |
const [pokemonId, setPokemonId] = React.useState<number>(); | |
const { pokemon } = usePokemon(pokemonId); | |
function handleSubmit(e: React.FormEvent<HTMLFormElement>) { | |
e.preventDefault(); | |
// @ts-ignore | |
setPokemonId(+e.target["pokemonId"].value); | |
} | |
return ( | |
<div> | |
<form onSubmit={handleSubmit}> | |
<label htmlFor="pokemonId"> | |
Pokemon ID: | |
<input type="text" id="pokemonId" name="pokemonId" /> | |
</label> | |
<button>search</button> | |
</form> | |
<pre>{JSON.stringify(pokemon, null, 2)}</pre> | |
</div> | |
); | |
} | |
export default function PokemonPage() { | |
return ( | |
<SWRConfig value={{ fetcher, suspense: true }}> | |
<div> | |
<ErrorBoundary FallbackComponent={ErrorFallback}> | |
<React.Suspense fallback="Loading..."> | |
<HomePage /> | |
</React.Suspense> | |
</ErrorBoundary> | |
</div> | |
</SWRConfig> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment