먼저 왜 리액트 쿼리를 쓰는가!
서버의 데이터를 가져오는 것!(패칭하는것) 그리고 캐싱을 잘하기 때문에!
그리고 리액트 쿼리도 컴포넌트들끼리 데이터 공유도 가능하기도 하다
로딩 성공 실패 표준화
React-Query는 캐싱을 통해 동일한 데이터에 대한 반복적인 비동기 데이터 호출을 방지하고, 이는 불필요한 API 콜을 줄여 서버에 대한 부하를 줄이는 좋은 결과를 가져온다.
캐싱이란 특정 데이터의 복사본을 저장하여 이후 동일한 데이터의 재접근 속도를 높이는 것을 말한다!
설치 방법
npm i npm i @tanstack/react-query-devtools // dev tool
npm i @tanstack/react-query
QueryClientProvider 컴포넌트를 최상단에 감싸고 QueryClient 인스턴스를 client 속성에 넣어준다.
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient()
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Example />
</QueryClientProvider>
)
}
서버에서 받아온 데이터를 리액트쿼리가 hydrate 한다
// 서버 컴포넌트
export defualt async function serverCn () {
const queryClinet = new Queryclient();
await queryClient.prefetchQuery({key,qyeryFu})
// 서버 컴포넌트에서 이걸 해줘야ㅕ한다!!@
const dehydrateState = dehydrate(queryClinet)
return (<HydrateionBoundary state={dehydrateState}> <HydrateionBoundary/>)
공식 문서의 예제에서는 prefetchQuery 메소드를 사용해서 데이터를 프리 패칭했다.
prefetchQuery 메소드는 데이터를 프리 패칭하고 캐시할 뿐, 어떠한 결과 값을 리턴하지 않는다.
반면에 fetchQuery 메소드는 데이터를 프리 패칭하고 캐시하고, 결과 값까지 리턴한다.
따라서, 목적에 적합한 메소드를 선택해야 한다.
단순히 프리 패칭만 하면 되는 경우 prefetchQuery 를 사용하면 되겠다.
하지만, 서버 사이드 렌더링 시점에서 패치한 데이터의 값 자체를 사용해야 한다면 fetchQuery 를 사용한다.
예를 들어, next-seo 같은 패키지를 사용한다고 가정해 보자.
서버 사이드 렌더링때 패치한 데이터를 SEO 의 props 값으로 넘겨주고 싶다면 실제로 패치한 데이터의 값 이 필요하다.
이럴때는 fetchQuery 를 사용해서 리턴 받은 값을 사용하면 된다.
자세한 내용은 공식 문서를 확인해 주세요!
queryclientfetchquery
const { isLoading, error, data } = useQuery('repoData', () =>
fetch('https://api.github.com/repos/tannerlinsley/react-query').then(res =>
res.json()
)
const requestData = useQuery(queryKey, queryFn, Option) 형태로 구성.
useQueries와 useInfiniteQuery 훅은 useQuery와 마찬가지로 서버에서 데이터를 가져올 때 사용한다. 여러 데이터를 병렬로 가져와야 할 때는 useQueries 훅을, 무한 스크롤과 같이 계속해서 데이터를 가져와야 할 경우 useInfiniteQuery 훅을 사용.
쿼리키(queryFn)가 다르면 호출하는 API가 동일해도 캐싱을 별도로 관리한다. Devtool에서도 쿼리키를 인식해서 디버깅하기 때문에 매우 중요!
참고로, React-Query에서는 최신의 데이터를 fresh한 데이터(굳이 서버에서 불어올 필요없고 캐시에서 써두 된다), 기존의 데이터를 stale한 데이터라고 말한다!!(기회가 되면 새로 서버에서 새로 데이터를 가져오자)
staleTime: 데이터가 fresh → stale 상태로 변경되는 데 걸리는 시간이다.
cacheTime(gcTime)
cacheTime은 데이터가 inactive한 상태일 때 캐싱된 상태로 남아있는 시간이다.(inactive:화면에서 데이터를 쓰고 이냐 안스고 있냐를 차이)
특정 컴포넌트가 unmount(페이지 전환 등으로 화면에서 사라질 때) 되면 사용된 데이터는 inactive상태로 바뀌고, 이때 데이터는 cacheTime만큼 유지된다.
cacheTime 이후 데이터는 가비지 콜렉터로 수집되어 메모리에서 해제된다.
데이터를 안쓰는 페이지 전환 시 안쓰는 데이터를 몇분 후 정리 할지 정하는 시간!
(가비지컬려션 타임: 안쓰는 데이터를 정리해줌 / 인네티브일때 메모리 정리 됨)
staleTime 만약 5뷴이면 5뷴동안 캐쉬에서 꺼내쓰는데새로 불러오지 않고 재사용하기 위함인데 (캐시를 얼마동안 오래 간직할까 의도)
gc타임이 만약 staleT보다 짧으면 gc타임은 inactive상태에서 해당 시간이 지나면 메모리를 정리하느건데 staleT보다 길어야 한다(gc타입은 staleT보다 길어야함!!)
만일 cacheTime이 지나지 않았는데 해당 데이터를 사용하는 컴포넌트가 다시 mount되면, 새로운 데이터를 fetch해오는 동안 캐싱된 데이터를 보여준다.
React Query에서 자주 사용되는 주요 기능들에 대해 알아보겠습니다. React Query는 API의 요청을 Query, Mutation의 두가지로 처리합니다.
Query 함수는 데이터 패칭용으로 사용되며, 보통은 GET으로 받아오는 대부분의 API에서 useQuery() 함수를 사용
Mutaion 함수를 사용하여 데이터를 업데이트하고 캐시를 업데이트 할 수 있습니다. Mutation 함수는 데이터 생성, 수정, 삭제 용으로 사용되며 POST, PUT, DELETE 요청시에 사용합니다.
export function useQuery<
TQueryFnData = unknown,
TError = unknown,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey
>
const { data, error } = useQuery<number, AxiosError>(['todo'], getTodo);
// data는 number | undefined의 타입을 가집니다.
// error는 AxiosError | null의 타입을 가집니다.
const { data } = useQuery<Todo[], AxiosError, number>(['todos'], getTodos, { select: todos => todos.length });
// select로 todos의 length을 data에 담기로 했으니,
// 세 번째 제네릭 타입에 number를 필수적으로 넣어줘야 합니다.
-TQueryKey : 첫번째 인자로 주는 queryKey타입을 명시적으로 지정
###useMutaion의 타입
export function useMutaion<
TData = unknown,
TError = unknown,
TVariables = void,
TContext = unknown
>
const { mutate } = useMutation<TodoResponse, AxiosError, number>(postTodo, {
onSuccess: (res, id) => {},
onError: (err, id) => {},
onMutate: id => {},
onSettled: (res, err, id) => {},
});
return <button onClick={() => mutate(5)}>add</button>;
출처:https://gusrb3164.github.io/web/2022/01/23/react-query-typescript/
출처: https://jaycode.tistory.com/39 [JAY⌨️CODE:티스토리]
https://xionwcfm.tistory.com/336
출처: https://jaycode.tistory.com/39 [JAY⌨️CODE:티스토리]