useMutation
카테고리 생성 기능을 구현하던 중, 카테고리 데이터를 서버로 POST 해줘야했다.
서버 데이터를 변경하는 요청은 (POST, DELETE 등) 대부분 특정 이벤트가 발생할 때 실행되어야 한다.
이는 useMutation
의 mutate
를 사용하여 구현할 수 있다.
카테고리의 name을 post하는 비동기 함수를 작성하고,
const categoryRequest = async (name: string) => {
const requestData = {
name: name,
};
const response = await axiosInstance.post(`${BASE_ENDPOINTS.CATEGORY}`, requestData);
return response;
};
useMutation을 return 하는 useCreateCategory
를 작성했다.
export const useCreateCategory = () => {
return useMutation<AxiosResponse<Category>, Error, string>({
mutationFn: categoryRequest,
onError: (error) => {
console.error('Error', error);
},
});
};
mutate
useMutation
을 선언한 useCreateCategory
안에 mutate라는 속성이 있는데, mutate는 useMutation을 조작할 수 있는 속성이다.
mutate
안에는 useMutation
의 비동기 함수에 들어갈 인자가 들어간다.
사용 예제
나는 mutate 함수명을 createCategory
로 지정해주었다.
onSuccess
옵션으로 createCategory가 성공했을 때의 로직을 처리,
isPending
, isError
를 사용하여 에러와 로딩 상태를 핸들링해줄 수 있다.
const { mutate: createCategory, isPending, isError} = useCreateCategory();
createCategory(categoryName, {
onSuccess: () => {
setCategoryName('');
setIsInputVisible(false);
},
});
}
{isPending && <Spinner />}
{isError && <>'카테고리 생성 중 오류가 발생했습니다.'</>}
*하나 주의할 점은 tanStack query v5에서는 isLoading 옵션이 사라졌다. isPending을 사용해야함!
공식문서에 자세히 나와있다.
상태코드에 따라 예외처리하기 with AxiosError
useMutation을 사용해서 POST, PUT 등 데이터를 변경할 때 , response에 에러가 발생하면 예외를 처리하도록 했다.
우선, 에러가 발생했을 때 서버에서 던져주는 응답을 살펴보자.
사용자가 아이디(이메일)과 비밀번호를 잘못 입력했다면, 403 코드와 함께 ‘아이디와 비밀번호가 일치하지 않습니다.’라고 메세지를 던져주고 있다.
나는 두가지 방법을 적용해보았다.
1. 서버에서 던져주는 메세지를 그대로 사용하는 방법
AxiosError
객체의 response
속성에서 data
객체를 추출하고, 그 안에 포함된 code
와 message
를 사용할 수 있다. 이때 타입 정의를 사용하여 data
객체의 타입을 명시해준다.
type ErrorData = {
code: number;
message: string;
};
return useMutation({
mutationFn: loginRequest,
onSuccess: (response) => {
{..성공로직}
},
onError: (error: AxiosError) => {
const errorResponse = error.response;
const errorData = error.response?.data as ErrorData;
if (errorResponse && errorResponse.status === 403) {
alert(errorData.message);
return;
}
alert('로그인 실패');
},
});
2. 상태코드에 따라 프론트에서 따로 처리하는 방법
첫번째 방법에서 message
를 가져오는 부분만 제외하면 된다.
response의 status
값을 바로 사용해도 되고, 위에서처럼 ErrorData
의 타입을 정의하고 code 값만 빼오면 된다.
onError: (error: AxiosError) => {
const errorResponse = error.response;
if (errorResponse && errorResponse.status === 403) {
alert('회원정보가 일치하지 않습니다.');
return;
}
alert('로그인 실패');
},
최대한 비동기 처리 로직을 분리하려고 노력했다.
그리고 예외처리를 useMutation
내부에서 하면 좋을지, mutate, isError 등 여러 옵션과 함께 외부 컴포넌트에서 하면 좋을지에 대한 고민을 꽤나 많이 한 것 같다.
나름 계속 썼다 지웠다 하면서 고민해본 결과, 적어도 상태코드에 따라 예외처리를 하는 경우는 useMutation
내부에서 처리하고 넘어가는게 코드의 가독성이나 유지보수성 측면에서 나은 것 같다는 생각이 든다.
'FE > React & TS' 카테고리의 다른 글
[TS] useQuery 커스텀 훅 사용하기 (0) | 2024.07.21 |
---|---|
[TS] onSubmit와 formData를 사용하여 form 유효성 검사하기 (0) | 2024.07.18 |
[TS] useInfiniteQuery와 useInView 훅으로 무한스크롤 구현하기 (0) | 2024.07.14 |
[TS] React Query와 Suspense, ErrorBoundary 함께 사용하기 (0) | 2024.07.14 |
프론트엔드에서 효과적으로 비동기 처리하기(feat. TanStack Query & Suspense) (0) | 2024.07.13 |