CRYPTO TRACKER -4-

제동현·2023년 2월 10일
0

React Query

React Query란 React 애플리케이션에서 서버 state를 fetching, caching, synchronizing, updating할 수 있도록 도와주는 라이브러리다.

react 버전이 18이면 타입스크립트에서 react query를 못 불러온다.

npm i @tanstack/react-query 를 입력해서 모듈을 설치해주자.

npm i -D @tanstack/react-query-devtools 이것도

그리고 @tanstack/react-query에서 useQuery를 사용할때 query key의 값은 대괄호로 묶어줘야한다

예시
js const { isLoading, data } = useQuery(["allCoins"], fetchCoins);

설치

  1. npm i react-query로 터미널에 설치해준다.

  2. index 페이지에 다음과 같이 추가해준다.

import { QueryClient , QueryClientProvider} from "react-query";
   
   const queryClient = new QueryClient()```
  
  다음 render쪽에 가서 감싸준다.
  
  ```js
root.render(
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
    <App />
  </ThemeProvider>
</QueryClientProvider>
);

그래서 React-Query를 어떻게 쓸것이냐

일단 api를 컴포넌트와 다른곳에 모아두는 작업부터 시작하자.

Coins에 있는 coin정보를 가져오는 fetch구문을 따로 src/api.ts 옮겨놨다.

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

다음 coins 파일의 function Coins 아래에

const {isLoading, data} = useQuery("allCoins", fetchCoins)

react-query 라이브러리의 useQuery Hook을 이용하여 다음과 같이 작성해 주었다.

어디서 많이 보던 구문 아닌가. 그렇다 왼쪽은 Loading을 담당하던 useState에서 많이 보던 그것이다.
저 구문의 뜻은 useQuery hook은 fetcher 함수를 부르고 fetcher 함수가 loading중이라면 react query는 그걸 알려줄거다.

기존 코드

  const [coins, setCoins] = useState<CoinInterface[]>([]);
  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);
    })();
   }, []);

React-query로 정리된 코드

const { isLoading, data } = useQuery<ICoin[]>(["allCoins"], fetchCoins);

와 이거참 ....

기존 코드에서 100개의 코인목록만 보여주는 setCoins(json.slice(0,100)); 는
data?.slice(0, 100)로 대체됬다 정말 멋져

또 react-query의 특징은 페이지 정보를 cache 해놓기 때문에 Loading을 매번보지 않아도 된다.
api에 매번 접근하지 않는다는것이다.

App.tsx 페이지에 import { ReactQueryDevtools } from "react-query/devtools"를 설치해주고

  return (
    <>
      <GlobalStyle />
      <Router />
      <ReactQueryDevtools initialIsOpen={true} />
    </>
  );

이렇게 코드를 작성해준다 그러면

리액트 화면에 다음과 같은 인터페이스가 생길건데 저 devtool에서현재 페이지가 가지고 있는 cathe가 무엇인지 확인 가능하다.

이제 Coin.tsx 페이지를 바꿔줄건데 Coins 페이지와 큰 차이는 없다

  const { isLoading: infoLoading, data: infoData } = useQuery<InfoData>(
    ["info", coinId],
    () => fetchCoinInfo(coinId)
  );
  const { isLoading: tickersLoaidng, data: tickersData } = useQuery<PriceData>(
    ["tickers", coinId],
    () => fetchCoinTickers(coinId)
  );

여기서는 InfoData와 PriceData가 필요한데

둘의 useQuery 구문에 2개의 query를 사용할시 같은 이름으로 사용할수 없다 그래서

isLoading: infoLoading , Date도 마찬가지로 data:infodata 로 코딩해주었다.

[coinId] 코드의 경우엔 react-query에서 캐시를 저장하기위해 고유한 key값이 필요하니
앞에다가 ["info",coinId]를 넣어 []의 앞은 카테고리 뒤는 각자 고유의 key값을 주었다.
return부분에서
js const loading = infoLoading || tickerLoading; 으로 설정해 주니
기존에 사용하던 loading도 오류없이 작동한다.

0개의 댓글