react-query hook에는 useQuery라는 기능이 존재한다.
아래는 react-query를 사용하기 전 coins컴포넌트의 코드이다.
function Coins() {
const [coins, setCoins] = useState<ICoin[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
(async () => {
const response = await fetch("https://api.coinpaprika.com/v1/coins");
const json = await response.json();
setCoins(json.slice(0, 100));
setLoading(false);
})();
}, []);
return (
<Container>
<Header>
<Title>Coin</Title>
</Header>
{loading ? (
<Loader>Loading...</Loader>
) : (
<CoinsList>
{coins.map((coin) => (
<Coin key={coin.id}>
<Link
to={{
pathname: `/${coin.id}`,
state: { name: coin.name },
}}
>
<Img src={`https://coinicons-api.vercel.app/api/icon/${coin.symbol.toLowerCase()}`} />
{coin.name} →
</Link>
</Coin>
))}
</CoinsList>
)}
</Container>
);
보다시피 렌더함수를 제외하고 api를 사용하기 위해 10줄의 코드를 작성하였다.
코드 설명을 하자면 coin api를 fetch해서 coins에 100개의 코인json을 저장해준 후
로딩중이라면 "loading..."을 띄우고 로딩이 끝나면 coin list를 렌더링한다.
그리고 useQuery를 사용한 코드로 변경해보았다.
react-query 사용을 위해 index.tsx에 QueryClientProvider를 추가해주었다.
const queryClient = new QueryClient();
const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
root.render(
<div>
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</QueryClientProvider>
</div>
);
export async function fetchCoins() {
return fetch("https://api.coinpaprika.com/v1/coins").then((response) => response.json());
}
function Coins() {
const { isLoading, data } = useQuery<ICoin[]>("allCoins", fetchCoins);
return (
<Container>
<Header>
<Title>Coin</Title>
</Header>
{isLoading ? (
<Loader>Loading...</Loader>
) : (
<CoinsList>
{data?.slice(0, 100).map((coin) => (
<Coin key={coin.id}>
<Link
to={{
pathname: `/${coin.id}`,
state: { name: coin.name },
}}
>
<Img src={`https://coinicons-api.vercel.app/api/icon/${coin.symbol.toLowerCase()}`} />
{coin.name} →
</Link>
</Coin>
))}
</CoinsList>
)}
</Container>
);
같은 코드인데 단 한줄의 코드로 같은 기능을 구현할 수 있게 되었다.
useQuery는 두개의 argument를 갖는다.
첫번째는 queryKey(고유하게 식별시켜줄 key이름), 두번째는 가져올 fetcher 함수이다.
fetcher함수에서 받아온 json값을 data에 담아준다. 이 data는 수정 전 코드의 useState를 이용한 coins를 대체한다.
또 useQuery가 대단한 것이 isLoading이라는 기능을 가지고 있다.
이것은 내가 useState로 loading,setLoading 을 만들었던 것을 자동으로 구현해준다.
또 한가지의 장점
react-query는 데이터를 캐시에 유지하고 있어 페이지를 왔다갔다 할 때 재로딩 되지 않는다.