React Query

김태경·2022년 10월 2일
0
post-thumbnail

리액트에서 API를 호출하여 화면에 뿌리는 것을 만드려면
간단하게 해도 state는 최소 2개가 사용되고
(data 저장용, loading 체크용 state) + fetch 함수 작성까지

코드가 꽤 길어지고 가독성이 떨어지게 된다.
그리고 만약 페이지 첫 방문시에 한번만 API를 호출하면 되는 상황이라고 치면 위와 같이 수동적으로 state를 만들어서 구현하게 되면
다른 페이지에 갔다가 다시 왔을 때 또 한번 더 API를 호출하게 되는 로직이 되는데 이는 상당히 비효율적 입니다.

위와 같이 긴 코드 + API 데이터 재사용 안됨 (물론 어떻게든 하면 될 수도)
이 2가지를 훨씬 더 짧고 섹시하게 해결하기 위해 나온 리액트 Hook이 바로 useQuery() 이고 React Query 입니다!

🦴 리액트 쿼리를 본격적으로 사용하기 전에 기본 셋팅하자!

  1. npm 설치
npm i react-query
  1. 루트 컴포넌트에서 감싸주기
const queryClient = new QueryClient();

<QueryClientProvider client={queryClient}>
   <App />
</QueryClientProvider>

🤓 Worst 상황을 만들어 보고 리팩토링 하자!

/* 더러운 코드 */

const [loading, setLoading] = useState<boolean>(true);
const [data, setData] = useState({});
  
useEffect(() => {
    (async () => {
      const res = await (
        await fetch(`https://api.coinpaprika.com/v1/coins/${coinId}`)
      ).json();
      
      setData(res);
      setLoading(false);
    })();
  }, []);

위와 같이 길고도 긴 fetch로 api를 호출하고 받은 데이터를 set하고
loading, data state 남발하는 코드를 섹시하게 바꿔 보겠습니다.

/* ReactQuery로 개선된 코드 */

// 모든 코인을 불러오는 fetch 함수 만들기
export default async function fetchCoins() {
  return await (
     await fetch(`https://api.coinpaprika.com/v1/coins`)
    ).json(); 
} 

// <ICoin[]>는 따로 만들어둔 코인 인터페이스의 배열 타입이라고 지정해준 것이다. tsx 이므로.
// useQuery()는 fetch 함수 실행 후 data로 값을 보내주고 값을 보내주기 전까지
// isLoading은 false이며 값이 전달되면 true로 바뀐다. 

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

📝 useQuery 알아보자

useQuery는 필수로 2개의 argument가 필요한데
첫 번째는 "query key" 두 번째는 "fetcher 함수"

query key는 고유 식별자이어야 함!
예를 들어 모든 코인의 데이터를 가져오는 쿼리라면 "allCoins"로 작명 가능

fetcher 함수는 API를 호출하는 fetch 함수를 넣어주면 되는데
보통 api.ts or js 처럼 따로 fetch 함수용 파일을 만들고
그 파일에 fetch 함수들 작성해서 export하여 사용한다.

🦈 Query 캐시

React Query 를 사용하면 자동으로 (아직 이론은 잘 모르겠음) 쿼리 키 이름의 캐시에 데이터를 저장하여 새로고침 해도 같은 api를 여러번 호출하지 않고 저장한 데이터를 재사용하여 훨씬 효율적이다. React Query가 섹시한 부분이라고 생각함!

😗 음... 그럼 같은 컴포넌트에서 useQuery()를 2개 이상 사용하면 같은 이름으로 isLoading, data가 사용되는데 어떡하죠?

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

위와 같이 : 붙여서 이름을 변경할 수 있음. 상황에 맞게 바꾸면 됨!

추가로 useQuery() 훅에서 세 번째 argument로
refetchInterval을 선택적으로 넣을 수 있는데 이를 설정해주면
설정한 시간 마다 다시 fetch를 실행한다!

React Query 기본을 배우셨습니다!

profile
FE 뉴비

0개의 댓글