참고로 FSD architecture로 파일 분리가 되어있음.
// login api 파라미터 타입
export interface PostLoginParam {
email: string;
password: string;
}
// 성공 응답에 response 타입
export interface LoginSuccessResponse {
data: {
accessToken: string;
refreshToken: string;
};
}
import { axiosInstance } from '@shared/api/instance';
import { REQUEST_URLS } from '@shared/constants/api';
import { LoginSuccessResponse } from './dto';
const postLogIn = async (email: string, password: string) => {
const response = await axiosInstance.post<LoginSuccessResponse>(REQUEST_URLS.postSignIn, {
email,
password,
});
return response.data;
};
export { postLogIn };
login api를 axios를 이용해서 post해주는 코드를 만들었다.
import { useMutation } from '@tanstack/react-query';
import { LoginSuccessResponse, PostLoginParam, postLogIn } from '@shared/api/authentication-api';
export const usePostLoginMutation = () => {
return useMutation<LoginSuccessResponse, Error, PostLoginParam>({
mutationFn: ({ email, password }) => postLogIn(email, password),
});
};
useMutation에 대한 타입 지정이 중요하다.
처음에 타입 지정해주지 않았더니, 파라미터로 넘겨줄 값들을 일일이 지정해주어야 했다.
declare function useMutation<TData = unknown, TError = DefaultError, TVariables = void, ... > ...;
useMutation에 대한 타입은 위와 같다고 한다.
딱 TData
TError
TVariables
3개 까지만 타입 지정을 해주었다.
TData
: 반환되는 값에 대한 타입
TError
: 에러
TVariables
: 파라미터 타입
const { mutate: postLoginMutate } = usePostLoginMutation();
hook으로 생성해둔 usePostLoginMutation
에서 postLoginMutate(mutate)
를 빼온다.
const handleSubmitLogin: SubmitHandler<PostLoginParam> = async (data) => {
postLoginMutate({ email: data.email, password: data.password });
};
로그인 버튼을 눌렀을 때 handleSubmitLogin
함수가 실행되게 만들고,
postLoginMutate
에 email과 password 인자 값을 넘겨준다!!
그럼 로그인 잘 된다!!
이렇게만 끝내면 갱.장.히. 아쉽다.
로그인은 성공할 수도 있고 실패할 수도 있다.
해당 부분에 대한 처리는 useMutation
에서도 해줄 수 있고, mutate
에서도 해줄 수 있다.
그런데 아래 주의사항을 꼭 읽어 보자!
useMutation()
에 등록된 콜백 함수들은 컴포넌트가 언마운트되더라도 실행이 되지만,mutate()
의 콜백 함수들은 만약 뮤테이션이 끝나기 전에 해당 컴포넌트가 언마운트되면 실행되지 않는 특징을 가지고 있다고 한다.그래서 다른 페이지로 리다이렉트한다든가, 혹은 결과를 토스트로 띄워주는 것과 같은 로직은
mutate()
를 통해 등록해 주어야 한다. 출처
그래서 나는 mutate
에서 작업해주었다.
const handleSubmitLogin: SubmitHandler<PostLoginParam> = async (value) => {
postLoginMutate(
{ email: value.email, password: value.password },
{
onSuccess: () => { // 성공했을 때
return toast.success('로그인 성공!');
},
onError: (error) => {
// 실패했을 때
if (error instanceof AxiosError) {
// axios에서 보낸 에러가 맞다면 true 값 반환
if (error.response?.status === 400) {
// error.response?.status 에 number 체크해서 아래 값 반환
return toast.error('이메일과 비밀번호를 다시 확인해 주세요.');
}
}
return toast.error('로그인 실패.');
},
},
);
};