티스토리 뷰

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에 일일이 리스트한 것과 동일한 효과를 낸다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함