Skip to content

Instantly share code, notes, and snippets.

@gabrielmlinassi
Last active October 16, 2022 13:29
Show Gist options
  • Save gabrielmlinassi/5410b1b7c31bfbace22b42f1fa45ce89 to your computer and use it in GitHub Desktop.
Save gabrielmlinassi/5410b1b7c31bfbace22b42f1fa45ce89 to your computer and use it in GitHub Desktop.
Test SWR data transformations
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