Skip to content

Commit 414bd81

Browse files
committed
main 🧊 return async demo
1 parent c58cad7 commit 414bd81

1 file changed

Lines changed: 67 additions & 69 deletions

File tree

‎packages/core/src/hooks/useAsync/useAsync.demo.tsx‎

Lines changed: 67 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,91 @@
1-
import { useAsyncEffect, useBoolean, useToggle } from '@siberiacancode/reactuse';
2-
import { Loader2Icon } from 'lucide-react';
3-
import { Fragment, useState } from 'react';
4-
5-
import { cn } from '@/utils/lib';
1+
import { useAsync, useCounter } from '@siberiacancode/reactuse';
2+
import { ArrowLeftIcon, ArrowRightIcon, Loader2Icon } from 'lucide-react';
63

74
interface Pokemon {
5+
base_experience: number;
6+
height: number;
87
id: number;
98
name: string;
9+
weight: number;
1010
}
1111

12-
const CHAINS = {
13-
bulbasaur: [1, 2, 3],
14-
charmander: [4, 5, 6],
15-
squirtle: [7, 8, 9]
16-
};
17-
18-
const getPokemons = async (ids: number[]) => {
12+
const getPokemon = async (id: number) => {
1913
await new Promise((resolve) => setTimeout(resolve, 1000));
20-
return Promise.all(
21-
ids.map((id) => fetch(`https://pokeapi.co/api/v2/pokemon/${id}`).then((res) => res.json()))
22-
);
14+
if (id === 3) throw new Error('Pokemon blocked for demo');
15+
return fetch(`https://pokeapi.co/api/v2/pokemon/${id}`).then((res) =>
16+
res.json()
17+
) as Promise<Pokemon>;
2318
};
2419

2520
const Demo = () => {
26-
const [chain, toggleChain] = useToggle<keyof typeof CHAINS>([
27-
'bulbasaur',
28-
'charmander',
29-
'squirtle'
30-
]);
21+
const counter = useCounter(1);
22+
const getPokemonQuery = useAsync(() => getPokemon(counter.value), [counter.value]);
3123

32-
const [pokemons, setPokemons] = useState<Pokemon[]>([]);
33-
const [isLoading, setIsLoading] = useBoolean(true);
24+
return (
25+
<section className='flex flex-col gap-4'>
26+
<div className='flex items-center justify-between gap-4'>
27+
<p>
28+
Index: <code>{counter.value}</code>
29+
</p>
3430

35-
useAsyncEffect(async () => {
36-
setIsLoading(true);
37-
const data = await getPokemons(CHAINS[chain]);
38-
setPokemons(data);
39-
setIsLoading(false);
40-
}, [chain]);
31+
<div className='flex gap-2'>
32+
<button
33+
disabled={counter.value === 1 || getPokemonQuery.isLoading}
34+
type='button'
35+
onClick={() => counter.dec()}
36+
>
37+
<ArrowLeftIcon className='size-4' /> Prev
38+
</button>
4139

42-
return (
43-
<section className='flex min-w-xs flex-col gap-4 md:min-w-md'>
44-
<div data-slot='tabs'>
45-
<div className='mb-6' data-slot='tabs-list'>
46-
{Object.keys(CHAINS).map((name) => (
47-
<button
48-
key={name}
49-
data-state={cn(chain === name && 'active')}
50-
data-variant='tabs-trigger'
51-
type='button'
52-
onClick={() => toggleChain(name as keyof typeof CHAINS)}
53-
>
54-
{name}
55-
</button>
56-
))}
40+
<button disabled={getPokemonQuery.isLoading} type='button' onClick={() => counter.inc()}>
41+
Next <ArrowRightIcon className='size-4' />
42+
</button>
5743
</div>
44+
</div>
45+
46+
<div className='w-full min-w-xs rounded-lg border p-4 md:min-w-md'>
47+
{getPokemonQuery.isLoading && (
48+
<div className='flex h-32 flex-col items-center justify-center gap-2 md:h-44'>
49+
<Loader2Icon className='size-5 animate-spin' />
50+
<p>Loading</p>
51+
</div>
52+
)}
5853

59-
<div data-slot='tabs-content'>
60-
{isLoading && (
61-
<div className='flex h-36 flex-col items-center justify-center gap-2'>
62-
<Loader2Icon className='size-6 animate-spin' />
54+
{getPokemonQuery.error && !getPokemonQuery.isLoading && (
55+
<div className='flex h-32 items-center justify-center md:h-44'>
56+
<p className='text-destructive'>{getPokemonQuery.error.message}</p>
57+
</div>
58+
)}
59+
60+
{getPokemonQuery.data && !getPokemonQuery.isLoading && !getPokemonQuery.error && (
61+
<div className='flex items-center justify-center gap-6 md:gap-10'>
62+
<div className='flex size-32 items-center justify-center md:size-44'>
63+
<img
64+
alt={getPokemonQuery.data.name}
65+
className='h-32 md:h-44'
66+
src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/${getPokemonQuery.data.id}.png`}
67+
/>
68+
</div>
69+
70+
<div className='flex flex-col gap-2 text-sm md:text-base'>
6371
<p>
64-
Loading <code>evolution</code> chain
72+
name: <code>{getPokemonQuery.data.name}</code>
6573
</p>
66-
</div>
67-
)}
6874

69-
{!isLoading && (
70-
<div className='flex h-36 flex-row items-center justify-between gap-2'>
71-
{pokemons.map((pokemon, index) => (
72-
<Fragment key={pokemon.id}>
73-
<div className='flex flex-col items-center gap-2'>
74-
<div className='flex size-20 items-center justify-center md:size-28'>
75-
<img
76-
alt={pokemon.name}
77-
className='h-20 md:h-28'
78-
src={`https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/${pokemon.id}.png`}
79-
/>
80-
</div>
75+
<p>
76+
height: <code>{getPokemonQuery.data.height}</code>
77+
</p>
8178

82-
<p className='text-sm capitalize'>{pokemon.name}</p>
83-
</div>
79+
<p>
80+
weight: <code>{getPokemonQuery.data.weight}</code>
81+
</p>
8482

85-
{index < pokemons.length - 1 && <div className='text-xl'>{'>'}</div>}
86-
</Fragment>
87-
))}
83+
<p>
84+
experience: <code>{getPokemonQuery.data.base_experience}</code>
85+
</p>
8886
</div>
89-
)}
90-
</div>
87+
</div>
88+
)}
9189
</div>
9290
</section>
9391
);

0 commit comments

Comments
 (0)