function useMutationQuery(queryKeys, api, options = {}) {
const queryClient = useQueryClient()
return useMutation(api, {
onSuccess: () => {
console.log('Success')
queryClient.invalidateQueries(queryKeys)
options.onSuccess && options.onSuccess()
},
onError: (error) => {
console.log('ERROR')
console.error(error)
options.onError && options.onError(error)
},
onSettled: options.onSettled,
})
}
export default useMutationQuery
----------------------------------------------------------------------------
import { useQuery } from '@tanstack/react-query'
// import axios from 'axios'
// import { getDestination } from '../api/myPage'
export default function useReactQuery(obj, key, api) {
const { isLoading, isError, data, isSuccess } = useQuery([key, obj], () => api(obj))
return { isLoading, isError, data, isSuccess }
}
// staleTime: 1000 * 60 * 5, // 데이터가 5분 동안 신선하다고 간주
// refetchInterval: 1000 * 60, // 1분마다 데이터를 다시 가져옴
데이터, key , api함수 인자 넘기는 훅스
React Query는 비동기 데이터를 가져오고, 캐시하고, 동기화하며, 업데이트하고, 관리하는 작업을 수행, 이 라이브러리를 사용하면 컴포넌트가 서버 상태와 더 자연스럽게 상호 작용할 수 있으며, 캐싱, 동기화, 백그라운드 업데이트 등의 기능이 편리하게 제공(Component의 Lifecycle 구애 x)
서버의 상태를 불러오고, 캐싱하며, 지속적으로 동기화하고 업데이트 하는 작업을 도와주는 라이브러리
리액트쿼리를 활용한 다양한 전략과 몇가지 패턴들을 알아보겠습니다.
패턴들을 활용하여 더 나은 데이터 관리와 성능 향상을 추구할 수 있습니다.
“리액트 쿼리는 GC(가비지 컬렉터)로 캐쉬된 데이터를 관리하기 때문에 유용한 성능을 가집니다”
Query Keys 설정: Query keys를 구조적으로 설정하여 여러 쿼리의 데이터를 쉽게 관리하세요.
useQuery(['user', userID], fetchUserData);
Dependent Queries: 하나의 쿼리가 다른 쿼리의 결과에 의존하도록 설정할 수 있습니다.
const { data: userID } = useQuery('getUserID', fetchUserID);
const { data: userData } = useQuery(['user', userID], fetchUserData, { enabled: !!userID });
⇒ userIdD가 존재할 때 실행되는 조건을 걸어주는 의존방식 (user 정보들을 필요할때 get가능)
Mutation과 Query Invalidation: useMutation 후에 캐시를 무효화하여 항상 최신 상태를 유지합니다.
const mutation = useMutation(updateUser, {
onSuccess: () => {
queryClient.invalidateQueries('user');
},
});
Optimistic Updates: 빠른 UI 반응성을 위해 미리 변경을 적용하고 나중에 동기화합니다.
const mutation = useMutation(updateUser, {
onMutate: (newData) => {
queryClient.cancelQueries('user');
const oldData = queryClient.getQueryData('user');
queryClient.setQueryData('user', newData);
return { oldData };
},
onError: (err, newData, context) => {
queryClient.setQueryData('user', context.oldData);
},
});
⇒ 내부적으로 미리 data를 변경하도록하여 디테일한 상황들을 제어할 수 있습니다. 여러 data가 겹치는 상황들을 모면할 수 있습니다.
Pagination and Infinite Queries: 대용량 데이터셋을 효율적으로 처리합니다.
useInfiniteQuery('todos', fetchTodos, {
getNextPageParam: (lastPage, allPages) => lastPage.nextPage,
});
Prefetching: 미리 데이터를 가져와 뷰 전환이 빠르게 진행되도록 합니다.
queryClient.prefetchQuery('user', fetchUserData);
Stale Time and Cache Time 설정: 쿼리의 데이터가 얼마나 오래 유지되어야 하는지, 언제 새로 가져와야 하는지 설정합니다.
useQuery('user', fetchUser, {
staleTime: 1000 * 60 * 5,
cacheTime: 1000 * 60 * 30,
});
⇒ 페이지네이션, 무한스크롤, 성능향상, 데이터 리셋 설정 등 다양하게 활용가능합니다.
import { QueryClient, QueryClientProvider } from "react-query";
// QueryClient 인스턴스 생성
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 5 minutes
refetchOnWindowFocus: false,
retry: 1,
},
mutations: {
onError: (error, variables, context) => {
// Handle error
},
onSettled: (data, error, variables, context) => {
// Code to run after success or error
},
},
},
});
staleTime: 데이터가 새로운 것으로 간주되는 시간을 설정합니다.
refetchOnWindowFocus: 윈도우 포커스가 변경될 때 자동으로 데이터를 다시 가져올지 여부를 설정합니다.
retry: 쿼리가 실패했을 경우 재시도할 횟수를 설정합니다.
onError, onSettled: 뮤테이션의 에러 핸들링과 성공/실패 후 실행될 코드를 설정합니다.
이런 식으로 QueryClient의 기본 설정을 커스터마이징하면, 앱 전체에서 이러한 설정을 공유할 수 있습니다. 이렇게 함으로써 각각의 쿼리와 뮤테이션에서 매번 같은 설정을 반복하지 않아도 되므로 코드의 중복을 줄이고 유지보수성을 향상시킬 수 있습니다.
function App() {
return (
<QueryClientProvider client={queryClient}>
{/* 하위 컴포넌트 */}
</QueryClientProvider>
);
}
⇒
staleTime: 데이터가 새로운 것으로 간주되는 시간을 설정합니다.refetchOnWindowFocus: 윈도우 포커스가 변경될 때 자동으로 데이터를 다시 가져올지 여부를 설정합니다.retry: 쿼리가 실패했을 경우 재시도할 횟수를 설정합니다.onError, onSettled: 뮤테이션의 에러 핸들링과 성공/실패 후 실행될 코드를 설정합니다.실제로 ag-grid 테이블이나 다양한 라이브러리로 다양한 내부 로직에서 리액트쿼리를 사용할 때, 그 라이브러리에 데이터가 적용이 안되는 문제점들을 경험./
https://github.com/ssi02014/react-query-tutorial
:자주 쓰이고 다양한 예시들이 들어있는 깃헙주소입니다.