
react-query
Hooks for managing, caching and syncing asynchronous and remote data in React. Latest version: 3.39.1, last published: a month ago. Start using react-query in your project by running `npm i react-query`. There are 851 other projects in the npm registry usi
www.npmjs.com
React Query
Hooks for fetching, caching and updating asynchronous data in React
react-query.tanstack.com
공식문서에서 확인할 수 있었던 간단한 코드
import { QueryClient, QueryClientProvider, useQuery } from 'react-query'
const queryClient = new QueryClient()
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Example />
</QueryClientProvider>
)
}
function Example() {
const { isLoading, error, data } = useQuery('repoData', () =>
fetch('https://api.github.com/repos/tannerlinsley/react-query').then(res =>
res.json()
)
)
if (isLoading) return 'Loading...'
if (error) return 'An error has occurred: ' + error.message
return (
<div>
<h1>{data.name}</h1>
<p>{data.description}</p>
<strong>👀 {data.subscribers_count}</strong>{' '}
<strong>✨ {data.stargazers_count}</strong>{' '}
<strong>🍴 {data.forks_count}</strong>
</div>
)
}
1. React-Query란?
React-Query는 간단히 비동기 통신 fetch 등을 사용하면서 서버 상태 관리 및 비동기 로직을 쉽게 다루게 해주는 라이브러리입니다.
간단하게 살펴보면 기본적인 async/await으로 코인 api로 요청을 보내 데이터를 가져오고자 할 때 코드를 작성한다면 다음과 같습니다
- Async / await를 통한 fetch 비동기 통신
useEffect(() => {
(async () => {
const infoData = await (
await fetch(`https://api.coinpaprika.com/v1/coins/${coinId}`)
).json();
setInfo(infoData);
setLoading(false);
})();
}, [])
데이터를 가져오는 훅을 최상단에 선언하고 데이터를 받기 위한 로직을 작성한 뒤 실제로 그 데이터가 넘어오게 됐을 때 setState로 넘겨주도록 코드를 작성할 수 있고 이 때 만약에 데이터가 아직 오지않았을 때 로딩 상태를 표현하기 위해 하나의 훅을 더 선언하고 코드를 몇 줄 더 작성하게 됩니다
- react-query 를 통한 fetch 비동기 통신
//component
const {isLoading: infoLoading, data:infoData } = useQuery<IInfoData>(
["info",coinId], () => fetchCoinInfo(coinId)
);
//api.jsx api 전송 정보를 다 모아놨다.
const BASE_URL = "<https://api.coinpaprika.com/v1>"
export function fetchCoins () {
return fetch(`${BASE_URL}/coins`).then((response) => response.json())
}
하지만 React-Query를 사용하게 된다면 우리는 요청을 보내는 콜백함수를 전달하기만 한다면 라이브러리에서 제공해주는 많은 기능들을 이용할 수 있으며 코드도 매우 간단해집니다
2. React-Query가 제공하는 기능
const {isLoading: infoLoading, data:infoData } = useQuery<IInfoData>(
["info",coinId], () => fetchCoinInfo(coinId)
);
물론 많은 기능들을 제공하고 있지만 제가 사용했던 기능들만 우선적으로 작성해보려고 합니다
2.1. 구조
공식문서를 확인해서 할 수 있는 기본적인 셋업을 제외하고 위 간단한 코드를 통해 알아보면 useQuery로 react hook과 유사한 구조를 가지고 있으며 두 가지의 인자값을 가지게 됩니다.
id와 callback함수 두가지를 받는데 id는 단순히 string 값으로 입력할 수 있지만 이후 서버 상태를 관리하기 위해 React-Query는 캐싱을 하게 되는데 이때 캐싱시키고 다시 불러오기 위한 키값을 가지게 됩니다.
react-query는 한번 받아온 데이터를 버리지않고 저장하고 있기 때문에 저장시킨 데이터를 빠르게 찾아오기 위한 key값이 됩니다.
["info",coinId]
두 번째로 데이터를 가져올 수 있는 fetch함수를 콜백으로 받게 되는데 이 함수를 실행시킨 값을 캐싱해서 저장하고 hook처럼 사용할 수 있게 만들어 줍니다
() => fetchCoinInfo(coinId)
2.2. isLoading
isLoading이란 현재 로딩중인지 아닌지를 알려주는 역할을 하는 useQuery hook의 값중 하나이고 useQuery가 fetch로 담아온 데이터 값을 기다리고 있습니다. useQuery훅의 인자로 2개가 들어가는데 쿼리의 unique한 key 그리고 promise return 값이 있는 함수가 필요하며 위에서는 json형태로 받아오고 있습니다.
2.3. 캐싱과 개발자 도구
만약 fetch 함수를 사용하게 된다면 위 api요청을 보내는 코드가 컴포넌트가 마운트 될 때마다 계속 실행될 수 있어 상당히 거슬릴 뿐만 아니라 성능에 안좋은 영향을 끼치게 되는데 그것을 방지해주는 역할을 합니다. 그 동작을 방지해주는 것이 앞서 확인했던 키값이며 키는 값이 중복되면 안되는데 키는 기본적으로 배열로 값을 저장하고 있습니다 즉 우리가 문자열로 키 값을 넣어도 react-query는 배열로 그 값을 저장하고 있습니다.하지만 값이 중복될 거 같다면 우리는 2개의 값을 배열로 만들어 저장하면 해결할 수 있습니다
만약 그것이 실제로 동작하는지 궁금하다면 간단한 설정을 사용해볼 수있는데 ReactQueryDevtools를 import하여 확인해볼 수 있습니다
<ReactQueryDevtools initialIsOpen={true}/>
import React, { useState } from 'react';
import styled, { createGlobalStyle } from "styled-components";
import Router from './Router';
import { ReactQueryDevtools } from 'react-query/devtools'
import { GlobalStyle } from './styles/global-styles';
function App() {
return (
<>
<GlobalStyle/>
<Router/>
<ReactQueryDevtools initialIsOpen={true}/>
</>
);
}
export default App;
아래와 같이 react-query의 키를 통하여 값을 미리 저장하고 있다가 사용자가 다시 같은 페이지에 접속한다면 굳이 api 재요청을 하지 않고 값을 가져와 보여주게 되므로 훨씬 향상된 로딩속도를 보여주게 됩니다. 개발자 도구와 같은 형태이며 현재 어떤 값을 캐싱하고 있는지 보여주고 있습니다

const {isLoading: infoLoading, data:infoData } = useQuery<IInfoData>(
["info",coinId], () => fetchCoinInfo(coinId),
{
refetchInterval: 5000,
}
);
이 외에도 옵션값으로 5초마다 다시 불러오는 기능을 하고 있습니다. 여러가지 기능이 있으니 공식문서를 확인하여 사용하면 됩니다.
'TIL > 개념정리' 카테고리의 다른 글
중첩 라우팅 / router hook (0) | 2022.07.04 |
---|---|
Redux in NextJS + typescript (2) | 2022.07.03 |
Recoil (0) | 2022.06.30 |
Redux (0) | 2022.06.29 |
상태관리 라이브러리 (0) | 2022.06.28 |