# npm
npm install react-query
# yarn
yarn add react-query
// src/index.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import "./styles/index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
const queryClient: QueryClient = new QueryClient();
// 다음처럼 옵션을 미리 설정할 수 있습니다.
// const queryClient: QueryClient = new QueryClient({defaultOptions: {
// queries: {
// retry: 0,
// useErrorBoundary: true,
// },
// mutations: {
// useErrorBoundary: true,
// },
// },});
root.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={true}></ReactQueryDevtools>
<App />
</QueryClientProvider>
</React.StrictMode>
);
reportWebVitals();
🔆 devTool은 ReactQuery가 제공하는 개발툴입니다.
필요없다면 제외하셔도 상관없어요
Get
Method를 위한 훅입니다.
const { isLoading, isError, data, error } = useQuery("key", ()=>api.get(...), {
refetchOnWindowFocus: false, // react-query는 사용자가 사용하는 윈도우가 다른 곳을 갔다가 다시 화면으로 돌아오면 이 함수를 재실행합니다. 그 재실행 여부 옵션 입니다.
retry: 0, // 실패시 재호출 몇번 할지
onSuccess: data => {
// 성공시 호출
console.log(data);
},
onError: e => {
// 실패시 호출
console.log(e.message);
}
//...옵션
,...options
});
if (isLoading) {
return <span>Loading...</span>;
}
if (isError) {
return <span>Error: {error.message}</span>;
}
};
queryKey
값이 들어갑니다.queryFn
true
일경우 옵션에 따라 자동으로 api 요청 함수(두번째 파라미터)가 실행됩니다.ReactQuery의 캐시는 직렬화되어 있는 Key값으로 해쉬되어 관리됩니다.
useQuery(['todos', { status, page }], ...)
useQuery(['todos', { page, status }], ...)
useQuery(['todos', { page, status, other: undefined }], ...)
위 코드는 순서와 상관없이 key값이 같기 때문에 모두 같은 쿼리로 취급합니다.
때문에 key값은 서로 다른 쿼리로 쓸 경우 unique해야 합니다.
useQuery(['todos'], fetchTodos)
// 🚨 잘못된 사용 ( 서로다른 쿼리지만 키가 같다.
useInfiniteQuery(['todos'], fetchInfiniteTodos)
// ✅ 사용 가능
useInfiniteQuery(['infiniteTodos'], fetchInfiniteTodos)
QueryKey를 Array형태로 넣으면 QueryFn내부에서 변수로 사용도 가능합니다.
const app = {
version: "12.1.1"
};
const result = useQuery(
["getRune", app.version],
params => {
console.log(params);
// {queryKey: ['getRune', '12.1.1'], pageParam: undefined, meta: undefined}
return api.getRunInfo(app.version);
},
);
ReactQuery는 기본적으로 데이터를 fetching 해온 후, 해당 데이터가 stale하다고 판단 될 때 데이터를 refetching합니다. 허나 항상 refetching을 하는 것은 성능상의 문제가 될 수 있기 때문에 사용자에게 최신 데이터를 제공해야하는 상황을 잘 생각해서 사용하여야합니다.
보편적으로 사용자가 최신 데이터를 봐라봐야 하는 상황은 다음과 같습니다.
리액트 쿼리는 기본적으로 다음과 같은 상황에서 Refetching을 합니다.
기본적으로 설정된 것은 위와 같지만 다음옵션설정과 개발자의 커스텀 트리거로 원하는 상황에서 리패치가 가능하게 바꿔줄 수 있습니다.
refetchOnWindowFocus, //default: true
refetchOnMount, //default: true
refetchOnReconnect, //default: true
staleTime, //default: 0
cacheTime, //default: 5분 (60 * 5 * 1000)
Post
method를 위한 훅입니다.
// 1
const savePerson = useMutation(mutationFn);
// 2
const savePerson = useMutation({
mutationFn: mutationFn
})
return 값은 useQuery
와 동일합니다. useMutation에선 key값은 optional입니다.
위 처럼 정의를 한후 실제로 이벤트를 발생시킬땐 mutate
를 사용합니다.
const savePerson = useMutation((person: Iperson) => axios.post('http://localhost:8080/savePerson', person)); // useMutate 정의
const onSavePerson = () => {
savePerson.mutate(person); // 데이터 저장
}
mutation으로 데이터를 수정하고 수정된 데이터를 다시 요청하고 싶을 때가 있을겁니다.
그때는 등록된 queryKey의 유효성을 제거해주면 staleTime, cacheTime에 상관없이 서버에 새로운 데이터를 요청할 수 있습니다.
const queryClient = useQueryClient(); // 등록된 quieryClient 가져오기
const savePerson = useMutation((person: Iperson) => axios.post('http://localhost:8080/savePerson', person), {
onSuccess: () => {
console.log('onSuccess');
queryClient.invalidateQueries('persons'); // queryKey 유효성 제거
},
}); // useMutate 정의
⚡️ 물론 useQuery와 useMutation이 같은 스코프에 정의 되어 있다면 refetch를 호출하여도 됩니다.