우당탕탕 개발일지
React Query - 1 본문
React Query란
React Query는 클라이언트에서 서버 데이터 캐시를 관리한다. 서버의 값을 클라이언트에 가져오거나, 캐싱, 값 업데이트, 에러핸들링 등 비동기 과정을 더욱 편하게 하는데 사용한다.
React 코드에서 서버 데이터가 필요할 때 axios를 통해 서버로 바로 이동하지 않고 React Query 캐시를 요청한다.
데이터 관리뿐만 아니라 React Query는 서버 상태를 관리 한다.
- 서버에 대한 모든 쿼리의 로딩 및 오류 상태를 유지하기에 수동으로 관리할 필요가 없다.
- 데이터의 페이지 매김(Pagination)을 제공하며, 무한 스크롤이 가능하다.
- 캐시에서 해당 데이터를 가져오기 때문에 서버에 연결할 때까지 기다릴 필요가 없다.
- 서버에서 데이터 변이나 업데이트를 관리할 수 있다.
- 데이터를 한번에 요청할 수 있기 때문에 중복 요청을 하지 않는다.
React Query Setting
- React Query 버전 3 다운로드
( React Query 버전 3와 리액트 쿼리 버전 4의 큰 차이점으로는 setQueryData에서 onSuccess가 호출되지 않는다. )
npm install react-query@^3
- react의 가장 기본이 되는 곳에 react-query를 사용하도록 설정
- QueryClient를 이용하여 queryClient 인스턴스를 만들어 주고, 이를 qeryclientProvider의 props로 전달
import React from "react";
import ReactDOM from "react-dom/client";
import { App } from "./App";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient();
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<QueryClientProvider client={queryClient}>
<React.StrictMode>
<App />
</React.StrictMode>
</QueryClientProvider>
);
Create React Query
export function PostDetail({ popst }) {
const {data, isLoading, isError, error} = useQuery{
["comments", post.id],
() => fetchComments(post.id)
);
if(isLoading) {
return <h3
fetchComments 함수는 비동기식이기 때문에 완료될 때까지 데이터는 useQuery에 정의되지 않는다. fetchComments 함수가 완료가 되어야지 데이터에 배열이 포함되고 컴포넌트가 렌더링 되어 매핑할 수 있다. React Query는 쿼리 키를 쿼리에 대한 의존성 배열로 취급한다. 따라서 쿼리 키가 업데이트되면 React Query가 새 쿼리를 생성해서 staleTime과 cacheTime을 가지게 되고 의존성 배열이 다르다면 완전히 다른 것으로 간주된다.
useQuery 로딩 및 오류 상태
isLoading과 isError는 데이터가 로딩 중인지 여부와 데이터를 가져올 때 오류가 있는지 여부를 알려주는 boolean이다.
const {data, isError, isLoading} = useQuery("posts", fetchPosts);
if (isLoading) return <h3>Loading...</h2>;
isFetching과 isLoading은 데이터를 가져오거나 업데이트 하는 과정에서 사용되는 상태 변수이다. isFetching은 비동기 쿼리가 해결되지 않았음을 의미하고, isLoading은 데이터를 가져오는 중이고 쿼리를 만든 적이 없어서 표시할 캐시 데이터도 없음을 의미한다. 이 두 유형은 페이지 매김(Pagination)을 진행할 때 캐시 된 데이터가 있을 때와 없을 때를 구분하기 위해 사용된다.
isFetching의 경우 async 쿼리 함수가 해결되지 않았을 때 즉, 데이터를 가져오는 상태인 경우 사용한다. isLoading의 경우 isFetching이 참이면서 쿼리에 대해 캐시된 데이터가 없는 상태일 경우 사용한다.
pagination
컴포넌트의 currentPage 상태를 통해 현재 페이지를 파악하는 페이지 매김 스타일이다. 데이터가 많을 경우, 페이지마다 요청하는 다른 쿼리 키가 필요하다.
export function Posts({ orderBy: string }) {
const [currentPage, setCurrentPage] = useState(1);
const [selectedPost, setSelectedPost] = useState(null);
const { data, isLoading, isError, error } = useQuery(["posts", currentPage], () =>
fetchPosts(currentPage),
{
staleTime: 2000,
}
);
return(
<div>
<button
disabled={currentPage <= 1}
onClick={() => {
setCurrentPage((previousValue) => previousValue -1);
}}
>
Previous page
</button>
</div>
)
}
쿼리 키를 배열로 업데이트해서 사용자가 다음 혹은 이전 페이지로 가는 버튼을 누르면 업데이트가 발생한다.
prefetch
데이터를 미리 가져와 캐시에 넣어두고, 이후 다시 가져오는 중에 캐시에 있는 데이터를 이용해 앱에 나타냄으로써 사용자 경험을 개선한다. prefetch 쿼리는 queryClient의 메서드이다.
useEffect(() => {
if (currentPage < maxPostPage) {
const nextPage = currentPage + 1;
QueryClient.prefetchQuery(["posts", nextPage], () =>
fetchPosts(nextPage)
);
}
}, [currentPage, QueryClient]);
maxPostPage 이전이라면 프리페칭이 이루어지지만, masPostPage를 넘어간다면 캐싱되어 있는 데이터가 없기 때문에 렌더링을 하지 못한다. 또한, 쿼리 키가 바꼈거나 이전 페이지로 돌아갔을 때 캐시에 해당 데이터가 있도록 keepPreviousData를 true로 설정해둔다.
'Front-end > React' 카테고리의 다른 글
Kakao API (1) | 2023.10.20 |
---|---|
React Query - 2 (0) | 2023.09.14 |
리액트 폴더 구조 (0) | 2023.08.06 |
Redux - 사용법 (0) | 2023.08.05 |
Redux - 전역 상태 관리 (0) | 2023.07.01 |