Coins.tsx
import { useState } from "react";
interface ICoin {
...
}
export const Coin = () => {
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, 20));
setLoading(false);
})();
}, []);
return (
{loading ? (
<Loader>Loading...</Loader>
) : (
{coins.map(coin => (
...
))}
}
);
}
npm install react-query
index.tsx에서 QueryClient와 QueryClientProvider를 import 한다.
QueryClient()로 인스턴스를 생성해 queryClient에 할당하고,
Provider로 App 컴포넌트를 감싸준 뒤 client로 queryClient를 넘겨주면
App 컴포넌트와 자식 컴포넌트는 queryClient를 사용할 수 있게 된다.
index.tsx
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { ThemeProvider } from "styled-components";
import { theme } from "./theme";
import { QueryClient, QueryClientProvider } from "react-query";
const queryClient = new QueryClient();
ReactDOM.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</QueryClientProvider>
</React.StrictMode>,
document.getElementById("root")
);
fetch 함수를 다른 파일로 분리시켜서 재사용성을 늘린다.
데이터를 fetch 하는 함수이므로 fetcher를 붙여서 네이밍했다.
api.ts
// 아래 둘 중 하나 선택해서 사용
// async, await 사용할 경우
export async function coinsFetcher() {
return await (await fetch("https://api.coinpaprika.com/v1/coins")).json();
}
// promise 사용할 경우
export async function coinsFetcher() {
return fetch("https://api.coinpaprika.com/v1/coins").then((response) =>
response.json()
);
}
useQuery라는 훅을 사용한다.
인자로 queryKey와 fetcher를 받아서 여러 status와 결과물인 data를 반환한다.
(useQuery가 반환하는 값 확인)
그 중 isLoading은 boolean 값으로 fetch 중엔 true, fetch가 완료되면 false이다.
Coins.tsx
import { useQuery } from "react-query";
import { coinsFetcher } from "../api";
interface ICoin {
...
}
export const Coin = () => {
const { isLoading, data } = useQuery<ICoin[]>("allCoins", coinsFetcher);
return (
{isLoading ? (
<Loader>Loading...</Loader>
) : (
{data?.slice(0,20).map(coin => (
...
))}
}
);
}
코드의 양이 획기적으로 줄었다.
queryClient를 콘솔에 출력해보면 아래의 결과가 나온다.
queryCache에서 볼 수 있듯이, 한 번 fetch한 데이터는 queryKey를 기준으로 캐싱해놓고 있어 컴포넌트 리렌더 시 데이터를 다시 가져오느라 발생하는 로딩이 방지된다.