코딩을 잘하고 싶은 코린이 동토니

React-Query V5 변경점 정리 본문

Web/JavaScript

React-Query V5 변경점 정리

dongtony 2024. 9. 2. 17:29

주요 변경점

useQuery

1. 컨벤션의 변화

기존 : queryOptions에 queryKey와 queryFn이 포함되지 않았음

const { data: paymentPromotions, isSuccess } = useQuery(
PaymentPromotionsKey.all(),
fetchPaymentPromotions,
)

변경 : queryOptions에 모들 property 추가

const { data: paymentPromotions, isSuccess } = useQuery({
queryKey: PaymentPromotionsKey.all(),
queryFn: fetchPaymentPromotions,
})

2. options의 변화

(많은 변화가 있지만 제일 많이 사용하는 위주로 정리)

  1. cacheTime (삭제) => gcTime (대체)
  2. onSuccess ,onSettled, onError(삭제) : 관련 콜백 일괄 삭제, 버그 발생의 주 원인
    1. 상태 동기화의 문제 (불필요한 렌더링 야기)
    2. 콜백이 실행되지 않을 가능성 (staleTime의 함정)
    3. onDataChanged와 같은 새로운 콜백? (구현 자체가 함정)

3. return 값 변화

  1. isPending (추가) : data fetch가 시작되지마자 true 로 진행 이후 error or success시 false
  2. isLoading vs isPending : isLoading의 경우 react-query에서의 정의는 데이터가 없는 상태 (v4기준) 따라서 false - true - false의 형태가 아닌 true - false의 형태를 가진 return값이였다.

해당 의미에 관해 의견이 분분하였고 v5에서 isPending이 isLoading을 대체, isLoading은 기존의 isInitialLoading을 대체하도록 변경 (false - true - false의 형태)

useMutation

1. 컨벤션의 변화

useMutation(() => postOrderNiconMoney({
	finalPrice: orderFinalPrice,
	paymentEmail: userPaymentEmail === '' ? null : userPaymentEmail,
	paymentMethodKey: selectedPaymentMethodKey as string,
	sellingPrice: niconMoneySellingPrice,
}),
	{
	onError: (error: any) => {
	handleOrderError(error)
	postMessage(isNativePortingVersion ? 'goBack' : 'close')
	},
	onSuccess: async (orderId) => {
	await handleOrder['niconMoney'](orderId)
	}},
)

변경 후

useMutation({
	mutationFn: () =>postOrderNiconMoney({
		finalPrice: orderFinalPrice,
		paymentEmail: userPaymentEmail === '' ? null : userPaymentEmail,
		paymentMethodKey: selectedPaymentMethodKey as string,
		sellingPrice: niconMoneySellingPrice,
	}),
	onError: (error: any) => {
	handleOrderError(error)
	postMessage(isNativePortingVersion ? 'goBack' : 'close')
	},
	onSuccess: async (orderId) => {
	await handleOrder['niconMoney'](orderId)
	},
})

useSuspenseQuery

suspense를 사용한 데이터패칭이 가능 기존 useQuery의 suspense 옵션삭제 => useSuspenseQuery를 통해 suspense를 통한 데이터 패칭을 별도로 관리 진행

suspense hook의 경우 로딩과 에러상태를 Suspense와 ErrorBoundary를 통해 관리하므로 언제나 status=success 및 undefined없이 data값을 반환

Optimistic updates

기존 낙관적 업데이트 처리 방식

useMutation({
	mutationFn: updateTodo,
	onMutate: async (newTodo) => {
	await queryClient.cancelQueries({ queryKey: ['todos', newTodo.id] })

	const previousTodo = queryClient.getQueryData(['todos', newTodo.id])

	queryClient.setQueryData(['todos', newTodo.id], newTodo)

	return { previousTodo, newTodo }
	},
	onError: (err, newTodo, context) => {

	queryClient.setQueryData(

	['todos', context.newTodo.id],

	context.previousTodo,
	)
},

	onSettled: (newTodo) => {

	queryClient.invalidateQueries({ queryKey: ['todos', newTodo.id] })
	},
})

변경된 처리 방식

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

useMutationState

useMutationState를 통해 캐싱된 mutation들의 상태를 전역에서 공유가능

filter와 select 옵션을 통한 전,후처리 가능

filter : 원하는 상태의 mutation만 호출 가능 select : 해당되는 mutation의 값을 처리 가능

const data = useMutationState({
  filters: { mutationKey }, // or {status : 'pending'}
  select: (mutation) => mutation.state.data,
})

useInfiniteQuery

initialPageParam (필수) 추가

이전 infiniteQuery를 사용할 때 초기값 세팅이 되어있지 않아서 pageParam의 초기값을 초기화 시켜줘야 했는데 해당 옵션을 정식적으로 지원

useInfiniteQuery({
  queryKey,
  queryFn: ({ pageParam }) => fetchSomething(pageParam),
  initialPageParam: 0,
  getNextPageParam: (lastPage) => lastPage.next,
})

maxPages option : 최대 페이지 설정 가능

prefetchInfiniteQuery : pages, getNextPageParam을 통해 한 개 이상의 page를 prefetch 가능

const prefetchTodos = async () => {
  await queryClient.prefetchInfiniteQuery({
    queryKey: ['projects'],
    queryFn: fetchProjects,
    initialPageParam: 0,
    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
    pages: 3, // 세 개 페이지
  })
}

TError의 기본타입 변경

기존 TError 가 unknown => Error 타입이 기본으로 자동 추론 되도록 변경 (커스텀 가능 )

Register를 통한 전역 에러 타입 설정

useQuery마다 에러 타입을 제네릭으로 알려주지 않고 Register 인터페이스로 기본 에러 타입을 정의할 수 있습니다.

declare module '@tanstack/react-query' {
  interface Register {
    defaultError: AxiosError;
  }
}
const { error } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups });
// const error: AxiosError | null

'Web > JavaScript' 카테고리의 다른 글

react-query fetch status에 관한 고찰  (2) 2024.09.02
JS 변수  (0) 2022.01.05
Arrow function 과 일반 function 의 this  (0) 2021.09.30