React 환경에서의 비동기 Query(질의) 과정을 도와주는 라이브러리로서 많은 사람들이 리액트 쿼리를 사용하는 이유를 정리해보았다.
- 캐싱
- get을 한 데이터에 대해 update를 하면 자동으로 get을 다시 수행한다. (예를 들면 게시판의 글을 가져왔을 때 게시판의 글을 생성하면 게시판 글을 get하는 api를 자동으로 실행 )
- 데이터가 오래 되었다고 판단되면 다시 get (invalidateQueries)
- 동일 데이터 여러번 요청하면 한번만 요청한다. (옵션에 따라 중복 호출 허용 시간 조절 가능)
- 무한 스크롤 (Infinite Queries (opens new window))
- 비동기 과정을 선언적으로 관리할 수 있다.
- react hook과 사용하는 구조가 비슷하다.
예시코드를 보자.
import React from 'react';
import axios from 'axios';
import { useQuery, useMutation } from 'react-query';
const API_URL = 'https://jsonplaceholder.typicode.com/posts';
// 게시글 목록을 가져오는 함수
const fetchPosts = async () => {
const { data } = await axios.get(API_URL);
return data;
};
// 새로운 게시글을 생성하는 함수
const createPost = async (newPost) => {
const { data } = await axios.post(API_URL, newPost);
return data;
};
const ExampleComponent = () => {
// 게시글 목록 가져오기
const { data: posts, isLoading, isError } = useQuery('posts', fetchPosts);
// 새로운 게시글 생성하기
const createNewPost = useMutation(createPost, {
onSuccess: () => {
// 새로운 게시글이 성공적으로 생성된 후에는 게시글 목록을 다시 불러옵니다.
queryClient.invalidateQueries('posts');
},
});
const handleCreatePost = async () => {
// 임의의 새로운 게시글 데이터 생성
const newPost = {
title: 'New Post',
body: 'Lorem ipsum dolor sit amet.',
userId: 1,
};
// 새로운 게시글 생성 요청 보내기
await createNewPost.mutateAsync(newPost);
};
if (isLoading) return <div>Loading...</div>;
if (isError) return <div>Error fetching data</div>;
return (
<div>
<h1>Posts</h1>
<button onClick={handleCreatePost}>Create New Post</button>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
};
export default ExampleComponent;
먼저 useQuery의 구조를 보자.
const { data } = useQuery(
queryKey, //응답 데이터의 Unique key. 응답 데이터를 캐싱할 때 사용
queryFunction, //Promise를 반환하는 함수. 이 쿼리 요청을 수행하기 위한 fetch, axios등의 함수를 의미.
options,
)
쿼리 키의 개념이 이해가 가지 않았는데 위의 예시 코드에서 이 부분을 보면 알 수 있었다.
// 게시글 목록 가져오기
const { data: posts, isLoading, isError } = useQuery('posts', fetchPosts);
// 새로운 게시글 생성하기
const createNewPost = useMutation(createPost, {
onSuccess: () => {
// 새로운 게시글이 성공적으로 생성된 후에는 게시글 목록을 다시 불러옵니다.
queryClient.invalidateQueries('posts');
},
});
새로운 게시글을 생성하고 후에 게시글 목록을 불러올때 글을 가져오는 과정에서 'posts' 라고 키를 지정해줬기 때문에 queryClient.invalidateQueries('posts');를 통해서 useQuery('posts', fetchPosts);를 또 한번 실행하게된다.
추가로 useQuery의 옵션에 해당 코드처럼 넣어보자
const { data } = useQuery(['data', getServerData,{
cacheTime: 60000, // 1분 동안 캐시로 저장
})
const { data } = useQuery(['data', getServerData,{
staleTime: 10000, // 10초 이내에는 캐시된 결과를 사용
})
cachetime은 첫 번째 요청 후 1분 동안은 같은 쿼리를 호출하더라도 서버로부터 데이터를 다시 받지 않고 캐시된 결과를 사용.
staleTime은 해당 데이터가 10초간 fresh한 데이터로 사용하고 이후는 stale 데이터로 바꾼다.
둘의 차이점은 cachetime은 만료 후에 삭제 되기때문에 다시 데이터를 받아와야해서 로딩이 이뤄진다. 하지만 staletime은 캐시엔 남아있지만 해당 데이터는 신선치 못한 데이터기 때문에 refetch 이후 새로운 데이터와 비교하여 바뀐 데이터만 바꾸기 때문에 캐시에 남아있는 데이터를 계속 보여줄 수 있다.
