본문 바로가기
개발로그/ReactNative

React Query 를 사용해보자. : useQuery

by 그리너리디밸로퍼 2023. 1. 25.

 

    React Query 설치 및 기본 사용방법

     

    (useQuery)Hooks 를 이용해서 Fetch 데이터에 접근 할 수 있게 해주고, 데이터를 알려준다. 또한 Loading stats, caching , 무한 스크롤 지원함. 

     

    설치 

     $ npm i react-query
     # or
     $ yarn add react-query

     

    사용방법  step 01. 

     

    • import 해준다. 
    • queryClient 를 생성한다. 
    • <QueryClientProvider>로 app(데이터를 사용할 컴포넌트) 을 감싼다.
    //App.js
    
    import {
       QueryClient,
       QueryClientProvider,
     } from 'react-query'
    
     
     // Create a client
     const queryClient = new QueryClient()
     
     function App() {
       return (
         // Provide the client to your App
         <QueryClientProvider client={queryClient}>
           <Movies />
         </QueryClientProvider>
       )
     }

     

    사용방법  step 02. 

    fetcher 만들기 - fetch 를 useQuery 훅의 인자로 사용한다. 

    useQuery("쿼리 키":String, "fetchef": function) 훅에 두개의 인자를 넣어 실행하면 끝

     

    기억을 위해 두개의 코드를 나열해보았다. 

    // fetch() 를 직접 사용한 코드  (24 Lines of code)

    //Movies.js
    
    import React, { useEffect, useState } from "react";
    
    const [loading, setLoading] = useState(true);
    const [nowPlaying, setNowPlaying] = useState([]);
    
    const getNowPlaying = async () => {
        const { results } = await (
          await fetch(`${API_URL}`
           )
          ).json();
    
        setNowPlaying(results);
      };
       
     const getData = async () => {
      await getNowPlaying();
      setLoading(true);
     }
     
     useEffect(()=>{
     	getData();
     },[]);

    // fetch 를 useQuery 훅의 인자로 활용한 코드 (almost 10 lines of code)

    //my-api.js
    
    const getNowPlaying = () =>
      fetch(`${BASE_URL}/trending/movie/week?api_key=${API_KEY}`).then((res) =>
        res.json()
      );
    //Movies.js
    
    import { useQuery } from "react-query";
    import { getNowPlaying, postTodo } from '../my-api'
    
    const {isLoading, data} = useQuery("nowPlaying",getNowPlaying);

     

    24줄의 코드를 약 10줄 이내로 줄일 수 있게 되었다. 

    useQuery{ isLoading, isError, data, error } 를 선택적으로 반환받아 사용할 수 있다. 위 예제는 isLoading, data 만 받아왔다. 추가적으로 어떤것을 받을 수 있는지는 여기로.

    "nowPlaying"은 queryKey로서 , 한 번 fetching(가져오기)된 data는 다시 가져오지 않아도 되도록 caching 한다.

    즉, 화면이 다시 그려질때마다(mount ) fetch 하지 않고 저장된 데이타를 쓰겠다는 뜻이다. 메모리를 아낄 수 있다는 뜻도 된다. 

     

    중요한 개념 1 :  React Query 's Power!

    React Query는 한번 fetch해서 가져온 쿼리 결과값을 쿼리키로 사용할 수 있게하며 다음 사항에 의해 자동으로 관리된다. 

    캐시된지 오래된 쿼리는 가비지컬랙션된다."inactive"(비활성화)된 인스턴스에서 쿼리한 결과값은 cacheTime 의 

    기본값(5분) 이 지나면 가비지 컬랙션 된다.

    다음의 경우에 자동으로 백그라운드에서 재수집(refetching)된다. 

    • 쿼리 마운트의 새 인스턴스
    • 창이 다시 초점을 맞춥니다.
    • 네트워크가 다시 연결됩니다.
    • 쿼리는 선택적으로 다시 가져오기 간격으로 구성됩니다.

    쿼리가 실패한다면 재시도는 3번 된다.

    일반적으로 캐싱전략을 구현하기 위해 사람들은 redux, Apollo 를 사용하기도 한다. fetch() 를 직접 사용한 코드 에서는 이러한 캐싱을 수동으로 구현하거나, 화면이 갱신되거나 state 데이터가 바뀔때마다 fetch되어 앱이 느려지는 문제가 발생한다. 

    ( 유료 API를 사용중이라면? fetch 될 때만다 돈이 나간다.;;)

     

    중요한 개념 2 :  refetch / isRefetching

    react query가 한번만 fetch를 하고 자동으로 fetch를 다시한다면, 수동으로 fetch를 해야할 때 어떻게 해야하는가? 아무리 usequery를 그냥 호출 한다한들 캐시에서 데이터를 가져온다니.. 

    이럴땐, useQuery 의 Options 중에 refetch 를 사용하면 된다. 

     

      const {
        isLoading: trendingLoading,
        data: trendingData,
        refetch: refetchTrending,
        isRefetching: isRefetchingTrending,
      } = useQuery("trending", moviesAPI.treding);

    refetch

     

    refetch 에 수동으로 refetch할 이름(함수명)을 지정하여 호출하는 시점에 refetch 된다.

     isRefetch

    마찬가지로 isRefetching을 가지고 refetch 되었는지 상태를 {true,false} 사용할 수 있다.

     isRefetching 을 로그로 찍은 화면. 


    마지막으로 사이드 프로젝트(Netflify 앱)에 Reqct Query를 적용할 때의 코드를 "적용 전"과 "적용 후"로 나누어 올려두었다. 

    App.js
    0.00MB
    Before_Movies .jsx
    0.00MB
    After_Movies.jsx
    0.00MB
    using_refetch_Movies.jsx
    0.00MB
    package.json
    0.00MB

     

    출처 및 자료: https://react-query-v3.tanstack.com/quick-start

    2023.01.25 - [개발로그/ReactNative] - CRNA로 만들어진 사이드프로젝트 Netflify 앱- Movies 화면 스냅샷

    2023.01.26 - [개발로그/ReactNative] - React Query 중요한 개념 : 캐싱과 쿼리 키

     

    728x90

    댓글