react-query더 공부하기

김예린·2024년 2월 27일
0

queryFn 의 매개변수로 Abort Signal 을 받을 수 있고, 이를 이용해서 Query 취소를 가능하게 합니다.

QueryFunctionContext

queryFn 은 매개변수로 QueryFunctionContext 이란 객체를 받습니다.

export const getTodos = async (queryFnContext) => {
  const { queryKey, pageParam, signal, meta } = queryFnContext;
	// queryKey: 배열형태의 쿼리키
	// pageParam: useInfiniteQuery 사용 시 getNextPageParam 실행 시 적용
	// signal: AbortSignal 을 의미 (네트워크 요청을 중간에 중단시킬 수 있는 장치)
	// meta: query에 대한 정보를 추가적으로 메모를 남길 수 있는 string 필드

  const response = await axios.get("http://localhost:5000/todos", { signal });
  return response.data;
};

useQuery({
  queryKey: ["todos"],
  queryFn: getTodos,
})
// example: <div onClick={(event) => {}}

페이지 컴포넌트 umount 시 Query 취소

API 요청 시 기본설정은 컴포넌트가 unmount 되도 네트워크 요청은 중단되지 않습니다.

GET 요청 시 abort signal 이 옵션으로 들어간 경우에만 unmount 시 자동으로 네트워크 취소가 됩니다.

import axios from 'axios'

const query = useQuery({
  queryKey: ['todos'],
  queryFn: ({ signal }) =>
    axios.get('/todos', {
      // Pass the signal to `axios`
      signal,
    }),
})

-수동으로 쿼리 취소

const query = useQuery({
  queryKey: ['todos'],
  queryFn: async ({ signal }) => {
    const resp = await fetch('/todos', { signal })
    return resp.json()
  },
})

const queryClient = useQueryClient()

return (
  <button
    onClick={(e) => {
      e.preventDefault()
      queryClient.cancelQueries({ queryKey: ['todos'] })
    }}
  >
    Cancel
  </button>
)

Optimistic Updates
서버 요청이 정상적으로 잘 될거란 가정하에 UI 변경을 먼저하고, 서버 요청 하는 방식. 혹시라도 서버 요청이 실패하는 경우, UI 를 원상복구(revert / roll back)합니다.

Prefetching
페이지 이동 전에 이동할 페이지의 쿼리를 백그라운드에서 미리 호출 (prefetching) 합니다.

캐시 데이터가 있는 상태로 해당 페이지로 이동 시 로딩없이 바로 UI를 볼 수 있습니다.

const prefetchTodos = async () => {
  // The results of this query will be cached like a normal query
  // prefetch 할 queryKey와 queryFn 은 이동할 페이지의 쿼리와 동일해야 적절합니다.
  await queryClient.prefetchQuery({
    queryKey: ['todos'],
    queryFn: fetchTodos,
  })
}

Paginated / Lagged Queries
다른 페이지 클릭 시 매번 Loading UI를 보여주기보다는 기존 UI를 유지하다가 서버로부터 새로운 데이터를 받아왔을 때 바꾸는 방식을 적용할 수 있습니다.

useQuery의 옵션 중 keepPreviousData를 true 로 바꾸면 이전 캐시데이터를 기반으로 isLoading 여부를 판단하게 합니다.

Infinite Queries
Data Fetching 이 일어날 때 마다 기존 리스트 데이터에 Fetched Data 를 추가하고자 할 때 유용하게 사용할 수 있는 hook 입니다.

더보기 UI 또는 무한스크롤 UI 에 사용하기에 적합합니다.

  • 실행 순서 정리

queryFn 실행 → 캐시 데이터 등록 { pages, pageParam } → getNextPageParam 실행 (리턴된 NextPageParam는 훅 내부 메모리에 저장. 캐시에 저장X) → (NextPageParam 이 undefined이 아니면) hasNextPage true로 상태변경 → fetchNextPage 실행 → queryFn 실행 (이 때 내부적으로 저장되어 있던 NextPageParam을 queryFn 의 매개변수로 넘겨줌)

  • pages 와 pageParams 를 갖는 캐시 데이터
    • useQuery 에서는 QueryFn 의 반환값이 캐시데이터로 등록됩니다.
    • useInfiniteQuery 에서는 QueryFn 의 반환값은 pages 배열의 요소로 추가되고, 매개변수로 받았던 pageParam은 pageParams 배열의 요소로 추가됩니다.
  • useInfiniteQuery 사용 시 주의사항
    • 훅 내부적인 동작원리로 인해 예상보다 잦은 리렌더링이 발생할 수 있습니다.
    • 연산량이 많은 코드가 있는 경우 useMemo 와 같은 memoization 적용을 특히 고려해야 합니다.
    • 리렌더링이 발생한다고 해서 실제 브라우저 렌더링이 발생하는 것은 아닙니다. (Virtual DOM 원리 이해 필요)
profile
아자아자

0개의 댓글