React | Migrating to TanStack Query(React) v5 변경

AEHEE·2023년 11월 14일
1

React

목록 보기
13/17
post-thumbnail

프로젝트에서 @tanstack/react-query를 v4 쓰고 있다가 이번에 v5로 변경하였다.
제일 큰 변화점은 v5부터는 객체 형식만 지원한다는 점이다.

참고
https://tanstack.com/query/v5/docs/react/reference/QueryClient
https://github.com/ssi02014/react-query-tutorial/blob/main/document/v5.md
https://wonsss.github.io/library/tanstack-query-v5/
https://www.moonkorea.dev/React-TanStack-Query-v5-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0-(%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%BF%BC%EB%A6%AC)

📍1.

v4에서는 useQuery(key, fn, options), useQuery({queryKey, queryFn, ...options}) 두 형태를 모두 지원했는데 이는 유지보수가 힘들고, 매개 변수 타입을 확인하기 위한 런타임 검사도 필요했기 때문에 오로지 객체 형식만 지원하도록 v5에서 변경되었다.

📍2.

queryClient.getQueryData, queryClient.getQueryState의 인수가 queryKey만 받도록 v5에서 수정되었다.
queryClient.getQueryData(queryKey)
queryClient.getQueryState(queryKey)

📍3.

Callbacks 함수의 onSuccess, onError, onSettled가 제거되었다.

📍4.

remove 메서드가 제거되었다.
쿼리를 제거해야하는 경우 queryClient.removeQueries({ queryKey: key })를 사용한다.

📍5.

isDatEqual을 사용하지 않고 동일한 기능인 structuralSharing으로 활용

📍6.

cacheTimegcTime으로 변경되었다.

📍7.

useErrorBoundary 옵션은 throwOnError로 이름이 변경됩니다. 리액트 훅의 접두사인 "use"와 특정 컴포넌트명인 "ErrorBoundary"의 사용보다는 옵션이 제공하는 기능에 맞게 다음 렌더 사이클에 에러를 다시 던지는 throwOnError로 변경됩니다.

📍8.

error의 기본 타입이 Error입니다. 거의 모든 경우에 Error 타입을 갖기 때문에 v5부터 error 필드는 Error 타입으로 추론됩니다.
커스텀 에러를 활용하거나 Error가 아닌 것을 활용하고 싶다면 아래 예제처럼 타입을 구체화할 수 있습니다.

const { error } = useQuery<Group[], string>({
	queryKey: ["groups"],
  	queryFn: fetchGroups,
});

📍9.

keepPreviousData 옵션과 isPreviousDataplaceholderData 옵션과 isPlaceholderData로 변경됩니다. v5에서 keepPreviousData는 리액트 쿼리에서 제공하는 함수(identity function)로 변경되는데요, 모듈에 불러와 placeholderData의 값으로 사용합니다.

useQuery({
  queryKey,
  queryFn,
  placeholderData: (previousData, previousQuery) => previousData,
  // identity function with the same behaviour as `keepPreviousData`
});

📍10.

Tanstack Query는 visibilitychange 이벤트를 지원하는 브라우저만 지원하도록 결정됐습니다. 따라서, 이제 visibilitychange 이벤트만 독점적으로 사용됩니다.

📍11.

커스텀 queryClient 인스턴스를 위해 커스텀 context prop이 제거되었습니다.

📍12.

refetchpage를 제거하고 maxPages가 추가 되었습니다.

📍13.

infinite Query 옵션에 명시적인 initialPageparam을 전달해야 합니다.
이전 버전에서는 queryFn의 pageParam이 undefined 값을 가져서 0 또는 초기 값을 정의했었는데 undefined는 직렬화되지 않아 initialPageParam 옵션이 추가됐습니다.

📍14.

Infinite query를 사용할 때 pageParam의 초기 값으로 사용될 initialPageParam 옵션을 전달해야 합니다. 이전 버전에서는 queryFn의 pageParam이 undefined 값을 가져서 0 또는 초기 값을 정의했었는데 undefined는 직렬화되지 않아 initialPageParam 옵션이 추가됐습니다.

📍15.

v4에서는 더 이상 페이지 없음을 나타내기 위해 명시적으로 undefined를 반환해야 했습니다. v5부터는 undefined 뿐만 아니라 null까지 포함하도록 확장됐습니다.

📍16.

서버에서의 retry 기본 값은 3에서 0으로 변경됩니다.

📍17.

status의 loadingpending으로 변경됩니다.
isLoadingisPending으로 변경됩니다.
isPending && isFetching의 기능인 isInitialLoadingisLoading으로 변경됩니다.

📍18.

v5부터는 낙관적 업데이트를 수행하는 방법을 제공합니다.

const queryInfo = useTodos()
const addTodoMutation = useMutation({
  mutationFn: (newTodo: string) => axios.post('/api/data', { text: newTodo }),
  onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),
})

if (queryInfo.data) {
  return (
    <ul>
      {queryInfo.data.items.map((todo) => (
        <li key={todo.id}>{todo.text}</li>
      ))}
      {addTodoMutation.isPending && (
        <li key={String(addTodoMutation.submittedAt)} style={{ opacity: 0.5 }}>
          {addTodoMutation.variables}
        </li>
      )}
    </ul>
  )
}

위 예제에서는 데이터를 캐시에 직접 쓰는 대신에 mutation이 실행중일 때 UI가 표시되는 방식만 변경합니다. 해당 방법은 낙관적 업데이트를 표시해야 하는 위치가 한 곳만 있는 경우에 효과적입니다

📍19.

infinite queriesnormal queries처럼 prefetch 할 수 있습니다. 기본으로 한 개 페이지에 대한 쿼리를 prefetch 하지만 pages 옵션과 getNextPageParam옵션으로 한 개 이상의 페이지를 prefetch 할 수 있습니다.

const prefetchTodos = async () => {
  // The results of this query will be cached like a normal query
  await queryClient.prefetchInfiniteQuery({
    queryKey: ["projects"],
    queryFn: fetchProjects,
    initialPageParam: 0,
    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
    pages: 3, // prefetch the first 3 pages
  });
};

📍20.

useQueries의 combine으로 응답(쿼리에 대한 정보 등)을 하나의 값으로 사용할 수 있습니다.
다만 위의 경우 쿼리의 data와 pending 값만 반환되고 쿼리에 대한 나머지 정보는 유실됩니다.

📍21.

data fetching에 대한 suspense가 안정화가 되었습니다.
useQuery에서 사용하던 suspense: boolean 옵션은 제거되고 useSuspenseQuery, useSuspenseInfiniteQueryuseSuspenseQueries이 추가되었습니다.
suspense와 관련된 자세한 내용은 suspense를 참고해주시길 바랍니다.

📍22.

Tanstack Query v5는 필요한 TypeScript 최소 버전이 v4.7입니다.

📍23.

Tanstack Query v5는 필요한 React 최소 버전이 v18.0입니다. 이는 React v18 이상에서만 사용할 수 있는 useSyncExternalStore 훅을 사용하고 있기 때문입니다.

📍24.

리액트 쿼리는 최신 브라우저에 최적화되어 있습니다.

Chrome >= 91
Firefox >= 90
Edge >= 91
Safari >= 15
iOS >= 15
opera >= 77
profile
UI개발자에서 FE개발자로 한걸음 더!

0개의 댓글