현재 useFormState 이 훅은 테스트버전이라 정상적으로 작동이 안되는 경우가 있다.
useActionState 로 변경 되었다고 하나 안될경우 다음과 같이 커스텀 훅으로 사용해 보자
~
import { useFormState } from "react-dom";
export default function AuthForm() {
const { formState, formAction } = useFormState(signup, null);
~
위와 같이 원래 react-dom 에서 useFormState 를 받아와 사용이 가능했지만 안되는 경우 useFormState 를 만들어서 사용해 보자.
auth-form.js
"use client";
import { signup } from "@/actions/auth-actions";
import Link from "next/link";
import { useState } from "react";
// 커스텀 훅 정의
// 이 훅은 폼 상태와 폼 제출 동작을 관리합니다.
function useFormState(action) {
const [formState, setFormState] = useState({ errors: {} });
// 폼 제출 동작 정의
// 폼 제출 시 호출되며, 서버 액션을 실행하고 결과에 따라 상태를 업데이트합니다.
const formAction = async (event) => {
event.preventDefault();
const formData = new FormData(event.target);
const email = formData.get("email");
const password = formData.get("password");
try {
// 서버 액션 호출 및 결과 처리
const response = await action({ email, password });
if (response.errors) {
setFormState({ errors: response.errors });
} else {
setFormState({ errors: {} });
}
} catch (errors) {
setFormState({ errors });
}
};
return { formState, formAction };
}
export default function AuthForm() {
// useFormState 훅을 사용하여 폼 상태와 폼 제출 동작을 가져옵니다.
const { formState, formAction } = useFormState(signup);
return (
<form id="auth-form" onSubmit={formAction}>
<div>
<img src="/images/auth-icon.jpg" alt="A lock icon" />
</div>
<p>
<label htmlFor="email">이메일</label>
<input type="email" name="email" id="email" required />
</p>
<p>
<label htmlFor="password">비밀번호</label>
<input type="password" name="password" id="password" required />
</p>
<div>
{/* 폼 상태에 오류가 있는 경우 오류 메시지를 표시합니다. */}
{formState.errors && (
<ul id="form-errors">
{Object.keys(formState.errors).map((error) => (
<li key={error}>{formState.errors[error]}</li>
))}
</ul>
)}
</div>
<p>
<button type="submit">유저 생성</button>
</p>
<p>
<Link href="/">Login with existing account.</Link>
</p>
</form>
);
}
client 가 아니라 server 에서 유효성 체크를 한다
auth-actions.js
"use server";
import { hashUserPassword } from "@/lib/hash";
import { createUser } from "@/lib/users";
import { redirect } from "next/navigation";
export async function signup({ email, password }) {
console.log(email, password);
let errors = {};
if (!email.includes("@")) {
errors.email = "이메일 정보가 유효하지 않습니다.";
}
if (password.trim().length < 4) {
errors.password = "비밀번호는 적어도 4글자 이상이어야 합니다.";
}
if (Object.keys(errors).length > 0) {
console.log("에러 반환 처리");
return { errors: errors };
}
const hashedPassword = hashUserPassword(password);
try {
createUser(email, hashedPassword);
} catch (error) {
console.log(error);
if(error.code ==='SQLITE_CONSTRAINT_UNIQUE'){
return {
errors: {
email:"이미 등록된 이메일 입니다."
},
};
}
throw error;
}
redirect('/training');
}














댓글 ( 0)
댓글 남기기