티스토리 뷰
React Query란?
React application의 데이터를 가져오기(fetching)위한 라이브러리
기능
- 캐싱(특정 데이터의 복사본을 저장하여 이후 동일한 데이터의 재접근 속도를 높이는 것)
- client 데이터와 server 데이터 간의 분리
- 백그라운드에서 오래된 데이터 업데이트
- 데이터가 얼마나 오래되었는지 알 수 있음
- 데이터 업데이트를 가능한 빠르게 반영
- 페이지네이션 및 데이터 지연 로드와 같은 성능 최적화
- 서버 상태의 메모리 및 가비지 수집 관리
- 구조 공유를 사용하여 쿼리 결과를 메모화
1. 설치
npm i @tanstack/react-query
# or
pnpm add @tanstack/react-query
# or
yarn add @tanstack/react-query
개발자도구: React Query의 모든 내부 동작을 시각화하는 데 도움이 되며 문제가 발생하면 디버깅 시간을 절약할 수 있다.
npm i @tanstack/react-query-devtools
2. 기본 설정 - QueryClientProvider, QueryClient
//index
import React from "react";
import ReactDOM from "react-dom/client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import App from "./App";
// client 생성
const queryClient = new QueryClient();
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<React.StrictMode>
{/* App에 client 전달 */}
<QueryClientProvider client={queryClient}>
<App />
<ReactQueryDevtools initialIsOpen={true} />
</QueryClientProvider>
</React.StrictMode>
);
3. data fetching - useQuery
- useQuery 공식 문서
- useQuery는 v5부터 인자로 단 하나의 객체만 받는다. 파라미터 queryKey, queryFn가 필수 값이다.
- queryKey: data를 식별하도록 하는 고유한 key값을 받음. 데이터를 cache할 때 개발자 도구에서 이 key값이 노출됨.
- queryFn: 실제 호출하고자 하는 비동기 함수가 들어간다. 필히 Promise를 반환하는 형태여야 한다.
useQuery가 반환하는 객체는 여러 가지가 있는데 그중 자주 사용하는 것들은 아래와 같다.
- isLoading / isFetching / isSuccess 등 : 현재 Query의 상태
- data : 응답에 성공한 데이터
- error : 응답 중 에러가 발생했을 때 반환되는 객체
React Query 적용 X
import React from "react";
import { useEffect, useState } from "react";
function App() {
const [loading, setLoading] = useState(true); // 로딩
const [coins, setCoins] = useState<{ name: string }[]>([]); // 코인 데이터
useEffect(() => {
(async () => {
const json = await (
await fetch(`https://api.coinpaprika.com/v1/coins`)
).json(); // 코인 데이터 비동기 통신
setCoins(json.slice(0, 100));
setLoading(false);
})();
}, []); // 새로고침 시 데이터를 가져오고 데이터가 준비되면 state에 저장하고 로딩은 false
return (
<>
<h1>리액트 쿼리 실습</h1>
{loading ? (
<p>Loading...</p>
) : (
<ul>
{coins.map((coin) => (
<li>{coin.name}</li>
))}
</ul>
)}
</>
);
}
export default App;
React Query 적용 O
import React from "react";
import { useQuery } from "@tanstack/react-query"; // useQuery import
async function fetchCoins() { // fetcher 함수 생성
return fetch(`https://api.coinpaprika.com/v1/coins`).then((response) =>
response.json()
);
}
function App() {
const { isLoading, data } = useQuery<{ name: string }[]>(
queryKey: ["allCoins"], // 고유한 querykey
queryFn: fetchCoins // fetcher 함수
);
return (
<>
<h1>리액트 쿼리 실습</h1>
{isLoading ? (
<p>Loading...</p>
) : (
<ul>
{data?.slice(0, 100).map((coin) => ( // data 렌더링
<li>{coin.name}</li>
))}
</ul>
)}
</>
);
}
export default App;
useQuery Hook을 활용해서 useEffect와 setState 과정을 useQuery를 이용하는 한 줄로 줄일 수 있다.
4. useQueries
여러 개의 useQuery를 한 번에 실행하고자 하는 경우, 기존의 Promise.all()처럼 묶어서 실행할 수 있도록 도와준다.
const ids = [1,2,3]
const results = useQueries({
queries: ids.map(id => (
{ queryKey: ['post', id], queryFn: () => fetchPost(id), staleTime: Infinity },
)),
})
// id를 기반으로 쿼리를 구분
// staleTime: 신선한 상태로 남아 있는 시간
5. useMutation
기본적으로 GET에는 useQuery,
PUT, UPDATE, DELETE에는 useMutation이 사용된다.
간단한 예시
// App.tsx
import React from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { updateItem, deleteItem } from './api';
const App: React.FC = () => {
const queryClient = useQueryClient();
const updateMutation = useMutation(updateItem, {
onSuccess: () => {
// 성공적으로 수정되면, 아이템 목록 쿼리를 무효화하여 최신 상태로 갱신
queryClient.invalidateQueries(['items']);
},
});
const deleteMutation = useMutation(deleteItem, {
onSuccess: () => {
// 성공적으로 삭제되면, 아이템 목록 쿼리를 무효화하여 최신 상태로 갱신
queryClient.invalidateQueries(['items']);
},
});
return (
<div>
<button
onClick={() => updateMutation.mutate({ itemId: 1, itemData: { title: 'Updated Item' } })}
>
Update Item
</button>
{updateMutation.isLoading && <p>Updating item...</p>}
{updateMutation.isError && <p>Error updating item</p>}
<button onClick={() => deleteMutation.mutate(1)}>
Delete Item
</button>
{deleteMutation.isLoading && <p>Deleting item...</p>}
{deleteMutation.isError && <p>Error deleting item</p>}
</div>
);
};
export default App;
// useMutation: 비동기 요청(여기서는 수정과 삭제 요청)을 수행하고, 그 결과를 관리. 요청 성공 시 'onSuccess' 콜백을 통해 후속 작업을 정의할 수 있다. 이 예제에서는 요청 성공 후 관련 쿼리를 무효화하여 데이터를 최신 상태로 갱신한다.
// 데이터 수정과 삭제 버튼: 사용자가 버튼을 클릭하면 각각 updateMutation.mutate와 deleteMutation.mutate를 호출하여 데이터 수정 또는 삭제 작업을 실행
6. useInfiniteQuery
무한 스크롤을 구현할 수 있다.
https://tanstack.com/query/latest/docs/framework/react/reference/useInfiniteQuery
https://velog.io/@strongorange/useInfiniteQuery-%EC%99%80-useInfiniteScroll-Hook
velog.io/@leemember/react-infinite-scroller
참고
https://velog.io/@kandy1002/React-Query-%ED%91%B9-%EC%B0%8D%EC%96%B4%EB%A8%B9%EA%B8%B0
'FrontEnd > 구현' 카테고리의 다른 글
상태관리와 Zustand (1) | 2024.03.19 |
---|---|
[구현 및 최적화 스터디] Firebase 로그인, 회원가입 with React Hook Form, yup (0) | 2024.03.19 |
[구현 및 최적화 스터디] 자동완성 검색(디바운싱과 쓰로틀링) (0) | 2024.03.10 |
[구현 및 최적화 스터디] useInfiniteQuery로 무한스크롤 구현, Masonry 레이아웃 (0) | 2024.03.07 |
[구현 및 최적화 스터디] Pagination (3) | 2024.02.22 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 디바운싱
- 오블완
- 핀터레스트
- zustand
- prettier
- web
- github
- Tanstack-Query
- 패키지 매니저
- Network
- Tanstack Query
- 이브와ICT멘토링
- style-lint
- Firebase
- git
- react-query
- 네트워크
- Masonry 레이아웃
- 티스토리챌린지
- 최적화
- 쓰로틀링
- Next.js
- 알고리즘
- sass
- react
- AI Challeng for Biodiversity
- eslint
- 캡스톤디자인
- React Query
- 무한스크롤
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
글 보관함