공부일지(TIL)/JS Framework + Library
[React Query] Tracked Query
Alledy
2023. 3. 16. 17:30
export const useTodosQuery = (select) =>
useQuery({ queryKey: ['todos'], queryFn: fetchTodos, select })
export const useTodosCount = () => useTodosQuery((data) => data.length)
function TodosCount() {
const todosCount = useTodosCount()
return <div>{todosCount.data}</div>
}
위 쿼리는 백그라운드에서 refetch할 때마다 두번씩 컴포넌트 리렌더링을 트리거한다.
{ status: 'success', data: 2, isFetching: true }
{ status: 'success', data: 2, isFetching: false }
isFetching의 상태값이 바뀌기 때문이다.
위와 같은 리렌더링을 피하고 싶다면 notifyOnChangeProps 를 사용할 수 있다.
이름에서 알 수 있듯이, 이것이 바뀔 때에만 옵저버에게 inform 하라는 것이다
export const useTodosQuery = (select, notifyOnChangeProps) =>
useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
select,
notifyOnChangeProps,
})
export const useTodosCount = () =>
useTodosQuery((data) => data.length, ['data'])
하지만 위 방식의 단점은 화이트리스트로 관리된다는 점이다.
만약 에러가 일어났을 때 리렌더링을 하고 싶으면 'error' 도 넣어줘야 하고, isLoading도 사용하고 싶으면 그것도 넣어줘야 한다. 누락됐을 때 문제가 생길 수 있다. 이게 불필요한 리렌더보다 더 최악이다.
이것을 해결할 수 있는 것이 있다.
const queryClient = new QueryClient({
defaultOptions: {
queries: {
notifyOnChangeProps: 'tracked',
},
},
})
function App() {
return (
<QueryClientProvider client={queryClient}>
<Example />
</QueryClientProvider>
)
}
쿼리 클라이언트 설정에서 위처럼 tracked 값을 설정하면 우리가 사용하는 필드에 대해서만 tracking하게 되며, array에 일일이 리스트한 것과 동일한 효과를 낸다.