so woon!

[REACT QUERY] React Query 1 본문

React Query/개념정리

[REACT QUERY] React Query 1

xowoony 2023. 4. 10. 13:31

학습일 : 2023. 04. 10


앞서 우리는
index.tsx 에서 이런 구조를 보았다.


<index.tsx>

(themeProvider 안에 있는 모든 것이 theme으로 접근 할 수 있다고 학습 했었다.)

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);

root.render(
  <ThemeProvider theme={darkTheme}>
    <App />
  </ThemeProvider>
);




그것과 마찬가지로 react query도 같은 맥락으로
queryClientProvider 안에 있는 모든 것은 queryClient에 접근할 수 있다고 보면 된다!!



리액트 쿼리를 쓴다면 useEffect, useState와 loading useState 들을 지워도 된다.
await, json(). setInfo() 도 없어도 된다.

터미널에 입력후 리액트 쿼리 설치

npm i react-query


설치가 완료되면
queryClient를 만들러 ㄱㄱ
그런 다음 provider를 만들어야 한다.

<index.tsx>

// import 해주고
import {QueryClient, QueryClientProvider} from "react-query";

// queryClient 작성
const queryClient = new QueryClient()

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);

root.render(
  // provider 를 만든다 - ThemeProvider, App 컴포넌트를 잘라내고 QueryClientProvider 안에 넣는다.
<QueryClientProvider client={queryClient}>
  <ThemeProvider theme={darkTheme}>
    <App />
  </ThemeProvider>
</QueryClientProvider>
);

 

 

이렇게 작성해주면 준비 완료



이제 리액트 쿼리가 우릴 어떻게 도와줄 수 있을까?

리액트 쿼리는 앞서 우리가 코인 api를 fetch 해서 불러오고
json으로 리턴하고 로딩을 멈추고 했던 일련의 과정들을 생략할 수 있게 만들어 준다.

리액트 쿼리를 사용하기 위해선 먼저,
fetcher 함수를 만들어야 한다.

살펴보자

src 폴더 아래에 api.ts 파일을 만들고
fetch 할때 써줬던 코드를 그 안에 넣을 것이다.

<api.ts>
Coins.tsx에서 fetch 했던 부분에서 const response, const json 부분을 잘라서 이곳에 붙여준다.

// fetchCoins 함수는 json data의 promise를 return 한다.
export async function fetchCoins() {
  const response = await fetch("https://api.coinpaprika.com/v1/coins");
  const json = await response.json();
  return json;
}



await과 async를 사용하는 대신 promise를 사용하는게 더 좋을듯 하고
코드가 너무 길기 때문에 아래와 같이 변경해주겠다.

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

이제 useQuery라고 불리는 hook을 사용할 것이다.


<Coins.tsx>
Coins에 return 윗부분을 모두 주석처리 해놓고 시작한다.
useQuery는 두개의 argument를 필요로 한다

(1. querykey - query의 고유식별자임  2. fetcher - 아까 api.ts에서 적어준 fetchCoins임)

useQuery의 멋진점은 useQuery라는 hook이 fetcher 함수 fetchCoins를 불러오고
그리고 fetcher 함수가 isLoading이라면 리액트쿼리가 말해준다는 점이다!
또한 fetcher함수가 끝나도 말해준다.


import { useQuery } from "react-query"; // import 해준다.
import { fetchCoins } from "../api"; // 아까 적어준 api.ts를 import 해준다.

function Coins() {
  const{ isLoading, data } = useQuery("allCoins", fetchCoins) // useQuery가 리턴하는 것들을 확인하고 받아오기
}



앞서 api.ts에서 fetchCoins는 json을 리턴했다.
따라서 fetchCoins가 끝나면 리액트쿼리는 그 함수의 데이터를
coins.tsx의

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


이곳 data에 넣어줄 것이다.




총정리

useQuery hook은
1.
내가 api.ts에 작성한 fetcher 함수를 부르고,
fetcher 함수가 loading 중이라면
Coins.tsx의

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


이부분에서 그것을 알려줄 것이며,

2.

fetcher함수가 끝나면
api.ts에 작성해준 json을

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


이곳의 data에 넣어줄 것이다.



<Coins.tsx>
따라서 return 부분에 loading ? 부분과 coins 부분이 에러가 생기는데(코드를 삭제해줬기 때문)
이 부분은 각각 
1. loading? 부분은 useQuery에서 오는 isLoading ? 으로 바꿔주면 되고
2. coins는 useQuery에서 오는 data로 바꿔주면 된다.
* 1, 2를 바꿔주면 typescript가 data가 뭔지 모르기 때문에 coin부분이 빨간줄이 뜨는데
전에 했던 것처럼

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


로 작성해주면 된다
또한 data 부분이 빨간줄이 뜨는 것은 data? 로 고쳐주자

고쳐주면 코드는 아래와 같다

 

<Coins.tsx>

import { useQuery } from "react-query";
import { Link } from "react-router-dom";
import styled from "styled-components";
import { fetchCoins } from "../api";

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

  return (
    <Container>
      <Header>
        <Title>Thorn Coin</Title>
      </Header>
      <SwitchTheme>테마 변경</SwitchTheme>
      {isLoading ? (
        <Loader>로딩중입니다...</Loader>
      ) : (
        <CoinsList>
          {data?.slice(0, 100).map((coin) => (
            <Coin key={coin.id}>
              <Link to={`/${coin.id}`} state={coin}>
                <Img
                  src={`https://cryptocurrencyliveprices.com/img/${coin.id}.png`}
                  alt=""
                />
                {coin.name}
              </Link>
            </Coin>
          ))}
        </CoinsList>
      )}
    </Container>
  );
}

export default Coins;

 

<api.ts>

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

 

 

실행결과는

이전과 같지만 더 좋은점이 생겼다.

 

1. 리액트쿼리를 사용하기 전 :  -> home 화면으로 갈 때 로딩이 생김(로딩 중 문구 출력됨)

2. 리액트쿼리를 사용한 후 : home 화면으로 돌아갈 때 로딩이 생기지 않음

(로딩이 더이상 생기지 않는 이유는 리액트 쿼리가 데이터를 캐시에 저장해두기 때문이라고 한다.)

 

 

이로써 리액트 쿼리를 이용하여 data를 쉽게 fetch하였고

더이상 불필요하게 로딩이 생기지 않고

총 9줄의 코드를 생략하는 결과를 얻었다.

 

너무 뿌듯하고 좋은걸!!!

 

 

 

'React Query > 개념정리' 카테고리의 다른 글

[REACT QUERY] useQuery 의 refetch interval 기능  (0) 2023.04.12
[REACT QUERY] React Query 3  (0) 2023.04.11
[REACT QUERY] React Query 2  (0) 2023.04.10
Comments