React Query로 데이터 fetching 하기

이춘구·2022년 2월 2일
3

React Query 적용 전

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 => (
          ...
      ))}
    }
  );
}

React Query 적용 후

1. react-query 설치

npm install react-query

2. QueryClient, QueryClientProvider

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

3. data fetch 로직 분리

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

4. fetcher 호출하는 컴포넌트의 코드 수정

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 => (
          ...
      ))}
    }
  );
}

코드의 양이 획기적으로 줄었다.

Data Caching

queryClient를 콘솔에 출력해보면 아래의 결과가 나온다.

queryCache에서 볼 수 있듯이, 한 번 fetch한 데이터는 queryKey를 기준으로 캐싱해놓고 있어 컴포넌트 리렌더 시 데이터를 다시 가져오느라 발생하는 로딩이 방지된다.

profile
프런트엔드 개발자

0개의 댓글