useQuery

Semmy·2022년 6월 9일
0

react-query hook에는 useQuery라는 기능이 존재한다.

아래는 react-query를 사용하기 전 coins컴포넌트의 코드이다.

useQuery 사용전

coins.tsx

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} &rarr;
              </Link>
            </Coin>
          ))}
        </CoinsList>
      )}
    </Container>
  );

보다시피 렌더함수를 제외하고 api를 사용하기 위해 10줄의 코드를 작성하였다.
코드 설명을 하자면 coin api를 fetch해서 coins에 100개의 코인json을 저장해준 후
로딩중이라면 "loading..."을 띄우고 로딩이 끝나면 coin list를 렌더링한다.

그리고 useQuery를 사용한 코드로 변경해보았다.
react-query 사용을 위해 index.tsx에 QueryClientProvider를 추가해주었다.

index.tsx

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>
);

useQuery 사용후

api.ts 생성

export async function fetchCoins() {
  return fetch("https://api.coinpaprika.com/v1/coins").then((response) => response.json());
}

coins.tsx

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} &rarr;
              </Link>
            </Coin>
          ))}
        </CoinsList>
      )}
    </Container>
  );

같은 코드인데 단 한줄의 코드로 같은 기능을 구현할 수 있게 되었다.
useQuery는 두개의 argument를 갖는다.
첫번째는 queryKey(고유하게 식별시켜줄 key이름), 두번째는 가져올 fetcher 함수이다.
fetcher함수에서 받아온 json값을 data에 담아준다. 이 data는 수정 전 코드의 useState를 이용한 coins를 대체한다.
또 useQuery가 대단한 것이 isLoading이라는 기능을 가지고 있다.
이것은 내가 useState로 loading,setLoading 을 만들었던 것을 자동으로 구현해준다.

또 한가지의 장점
react-query는 데이터를 캐시에 유지하고 있어 페이지를 왔다갔다 할 때 재로딩 되지 않는다.

profile
Web Developer

0개의 댓글