로그인 페이지를 구현한다고 가정해보자.
Form의 기본적인 구조는 다음과 같다.
<Form>
<FormField
control={...}
name="..."
render={() => (
<FormItem>
<FormLabel />
<FormControl>
{ /* Your form field */}
</FormControl>
<FormDescription />
<FormMessage />
</FormItem>
)}
/>
</Form>
"use client"
import { z } from "zod"
const formSchema = z.object({
email: z.string().email({
message: "유효하지 않은 이메일 주소입니다.",
}),
password: z.string().min(6, {
message: "비밀번호는 최소 6자 이상이어야 합니다.",
}),
});
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { signIn } from "next-auth/react";
type FormData = z.infer<typeof formSchema>;
export function Page() {
// 1. Define your form.
const form = useForm({
resolver: zodResolver(formSchema),
defaultValue: {
email: "",
password: "",
},
});
// 2. Define a submit handler.
const onSubmit = async (data: FormData) => {
const { email, password } = data;
const redirect_uri = (searchParmas.get("redirect_uri") as string) || undefined;
const response: any = await singIn("credentials", {
email,
password,
redirect: false,
callbackUrl: redirect_uri,
});
if (!response.ok) {
if (response.status === 401) {
if (response.error === "USER_NOT_FOUND") {
setOpenConfirmRegister(true); // AlertDialog 컴포넌트를 열고 닫기 위한 setState
return;
} else if (response.error === "PASSWORD_INCORRECT") {
alert("비밀번호가 일치하지 않습니다.");
return;
}
}
alert("로그인에 실패했습니다. 다시 시도해주세요.");
return;
}
};
}
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormControl>
<Input placeholder="이메일" {...field} type="email" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">
로그인
</Button>
</form>
</Form>;
<div onClick={onRouteRegister}>또는 회원가입</div>
const onRouteRegister = async (e: React.MouseEvent) => {
const redirect_uri = (searchParams.get("redirect_uri") as string) || undefined;
router.push(`/register/?email=${form.getValues("email")}&redirect_uri=${redirect_uri}`);
};
onSubmit 함수 안에서 확인할 수 있다. 회원정보가 없는 경우, 아래 조건문에 걸리게 된다.
if (!response.ok) {
if (response.status === 401) {
if (response.error === "USER_NOT_FOUND") {
setOpenConfirmRegister(true);
const [openConfirmRegister, setOpenConfirmRegister] = useState(false);
shadcn/ui의 alertDialog 컴포넌트를 이용해 결과를 보여준다.
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
<AlertDialog open={openConfirmRegister} onOpenChange={setOpenConfirmRegister}>
<AlertDialogContent>
<AlertDialogHeader>
<ExclamationIcon/>
<AlertDialogTitle>가입되지 않은 이메일입니다.</AlertDialogTitle>
<AlertDialogDescription>회원가입을 진행하시겠습니까?</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>취소</AlertDialogCancel>
<AlertDialogAction onClick={onRouteRegister}>회원가입</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
else if (response.error === "PASSWORD_INCORRECT") {
alert("비밀번호가 일치하지 않습니다.");
return;
}