Tanstack Query의 에러 핸들링을 위해 블로그들을 찾아보면
useCallback을 사용하여 핸들러 훅을 만드는 것을 찾아볼 수 있음.훅을 만들어서 사용하는 방법과 이전에 작성한 에러 핸들링 with Tanstack Query #1의 방식을 비교하고자 함.
index.tsx에서 사용 불가App.tsx에서 사용해야한다// utils
export const useApiError = () => {
const handleError = useCallback((error: unknown) => {
// 에러 핸들링 with Tanstack Query #1 코드 참고
}, []);
return { handleError };
};
// App.tsx
function App() {
const { handleError } = useApiError();
const [queryClient] = useState(() => new QueryClient({
queryCache: new QueryCache({
onError: (error, query) => handleApiError(error),
}),
mutationCache: new MutationCache({
onError: (error, _variables, _context, mutation) => handleApiError(error),
}),
}));
return (
<QueryClientProvider client={queryClient}>
{/* ... */}
</QueryClientProvider>
);
}
handleError를 왜 useCallback으로 썼는지useCallback으로 만들어짐React Query 훅의 onError로 넘김useCallback으로 안하면 함수가 새로 만들어져서 React Query 내에서 불필요한 리패칭이나 리렌더링이 생길 수 있음목적 : 컴포넌트 리렌더링 시
QueryClient재생성되는거 방지하기 위해
new QueryClient도 객체임 → 렌더링시마다 새로운 인스턴스가 계속 생성됨 → 참조값이 다르니까 React는 새로운 값으로 인식해서 리렌더링함 → 같은 인스턴스를 계속 써야 캐시/쿼리 상태가 유지가 정상적으로 되는데, 새로운거를 만드니까useState(() => ...)로 첫 렌더링 시 한 번만 실행되고 값 유지 → 객체 재생성 방지✅ 전역 QueryClientProvider vs 컴포넌트 내부 QueryClientProvider 차이
전역 QueryClientProvider에서는
index.tsx나 앱 최상단에 한 번만QueryClient인스턴스 생성하고,QueryClientProvider로 감쌈- 이 경우
queryClient객체는 앱 라이프사이클 내내 한 번만 생성되고 재사용됨- 그래서 전역
onError핸들러도 한 번만 등록되고 함수 참조가 계속 동일하니까useCallback필요없음컴포넌트 내부 QueryClientProvider에서는
App.tsx같은 컴포넌트 내부에서QueryClientProvider와QueryClient를 생성하면- 컴포넌트가 리렌더링 될 때마다 새로운 인스턴스 생성하니까 훅을
useCallback으로 감쌌고,queryClient도 객체니까useState로 한 번만 생성하도록 해서 재사용결론 : 전역은 앱 시작 시 1회
queryClient생성하고, 컴포넌트 내부는 매 렌더 시마다 생성하니까useCallback이나useState가 필수