현재 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)
댓글 남기기