auth.js, react-hook-form에 useTransition 사용기 !!
거의 대부분의 서비스에서는 회원가입과 로그인 기능이 존재합니다.
현재 진행중인 프로젝트에서는 세션, 토큰관리를 도와주는auth.js(next-auth)
와 제출양식의 유효성검증 및 여러 상태관리를 도와주는 react-hook-form
을 사용하고 있습니다.
우선 마주한 문제는 react-hook-foom
을 사용하기 위해서는 컴포넌트 내부 상단에 use client
선언을 해줘야 합니다. 그런데 이렇게되면 auth.js
의 signIn
메소드는 서버에서 동작하는 함수이므로 사용할 수 없게 됩니다. 코드로 보자면,
'use server';
export const signInWithCredentials = async (data: LoginInputsValues) => {
try {
await signIn('credentials', {
email: data.email,
password: data.password
});
} catch (error) {
if (error instanceof CredentialsSignin) {
return { message: error.cause as unknown as string };
}
}
redirect('/financial-product');
};
use server
를 선언했기 때문에 signInWithCredentials
을 호출할 때 서버액션을 사용해야 합니다.
react-hook-form
을 사용하지 않는다면 아래와 같은 방법으로 양식을 제출할 수 있습니다.
// 서버컴포넌트인 경우
<form action={signInWithCredentials}>
// ...
</form>
// 클라이언트 컴포넌트이면서 useFormState를 사용하는 경우
const [state, action] = useFromState(signInWithCredentials, {
message: ''
})
<form action={action}>
// ...
</form>
하지만, 저의 경우에는 react-hook-form
을 사용하여 유효성검사를 하는 코드를 작성했기 때문에 react-hook-form
의 handleSubmit
메소드를 사용하여 양식을 제출해야합니다.
<form onSubmit={handleSubmit((data) => signInWithCredentials(data))}>
// ...
</form>
하지만 이렇게 작성하면 다음과 같은 에러가 발생합니다.
use server
를 사용하는 서버액션 함수에는 일반객체만 전달할 수 있다는 내용이었습니다.
그래서 열심히 구글링한 결과 useTransition
으로 해결할 수 있다는 글을 찾았습니다.
해당 논의를 참고하여 프로젝트에 적용해 문제를 해결할 수 있었습니다.