React

 

 

현재 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');
  
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

Every man to his taste. (기호는 사람마다 다르다. 各樣各色)

댓글 ( 0)

댓글 남기기

작성