React-query로 데이터를 가져오고 업데이트하는 부분을 따로 커스텀 훅을 만들어 관리하는 작업을 했다.
커스텀 훅 적용하기 이전 ReservationDetail.tsx
'use client';
import Loading from '@/app/loading';
import { useQuery } from '@tanstack/react-query';
import { useParams } from 'next/navigation';
import { getUserReservation } from '../_lib/getUserReservation';
import ReservationList from './ReservationList';
export const ReservationDetail = () => {
const params = useParams();
const { id: userId } = params;
const {
isLoading,
error,
data: reservations,
} = useQuery({
queryKey: ['mypage', 'profile', 'reservation'],
queryFn: () => getUserReservation(userId as string),
});
if (isLoading) return <Loading />;
if (error) return <p>{myReservationError.message}</p>;
};
커스텀 훅 적용하기 이전 ReservationList.tsx
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { deleteUserReservation } from '../_lib/deleteUserReservation';
const ReservationList = () => {
const queryClient = useQueryClient();
const deleteReservationMutaion = useMutation({
mutationFn: () => deleteUserReservation(isOpenReservationComplete!),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['mypage', 'profile', 'reservation'],
});
},
});
const handleDelete = () => {
deleteReservationMutaion.mutate();
};
}
커스텀 훅 useMyReservationQuery.ts
import { deleteUserReservation } from '@/app/profile/[id]/_lib/deleteUserReservation';
import { getUserReservation } from '@/app/profile/[id]/_lib/getUserReservation';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useParams } from 'next/navigation';
export const useMyReservationQuery = (reservationId?: string) => {
const params = useParams();
const userId = params.id;
const {
isLoading: isMyReservationLoading,
error: myReservationError,
data: reservations,
} = useQuery({
queryKey: ['mypage', 'profile', 'reservation'],
queryFn: () => getUserReservation(userId as string),
});
const queryClient = useQueryClient();
const { mutate: reservationsMutate } = useMutation({
mutationFn: () => deleteUserReservation(reservationId as string),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['mypage', 'profile', 'reservation'],
});
},
});
return {
isMyReservationLoading,
myReservationError,
reservations,
reservationsMutate,
};
};
⚒️ 커스텀 훅 적용 ReservationDetail.tsx
커스텀 훅을 이용하니 불필요한 코드가 많이 줄어들었다.
'use client';
import Loading from '@/app/loading';
import { useMyReservationQuery } from '@/hooks/useMyReservationQuery';
export const ReservationDetail = () => {
const { isMyReservationLoading, myReservationError, reservations } =
useMyReservationQuery();
if (isMyReservationLoading) return <Loading />;
if (myReservationError) return <p>{myReservationError.message}</p>;
}
⚒️ 커스텀 훅 적용 ReservationList.tsx
커스텀 훅을 적용하면서 발생한 오류이다.
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
<커스텀 훅을 적용하면서 오류가 발생한 코드>
const ReservationList = () => {
const handleDelete = () => {
const { reservationsMutate } = useMyReservationQuery(isOpenReservationComplete!);
reservationsMutate();
};
}
👉 hook을 호출할 때 함수형 컴포넌트의 최상위 부분에서 호출하지 않아서 발생한 문제이다.
💡 hook 호출하는 코드를 최상위 부분으로 옮긴다.
<오류 해결한 코드>
import { useMyReservationQuery } from '@/hooks/useMyReservationQuery';
const ReservationList = () => {
const { reservationsMutate } = useMyReservationQuery(
isOpenReservationComplete ?? isOpenReservationComplete!,
);
const handleDelete = () => {
reservationsMutate();
};
}