UseForm으로 회원가입만들기(1탄)

밍글·2023년 3월 13일
2

UseForm

1. UseForm이란

UseForm이란 React에서 form의 validation을 도와주는 라이브러리이다. 이 라이브러리를 사용할 경우 하나의 객체를 선택적 인수로 사용한다.
설치 방법 : npm install react-hook-form

2.UseForm을 사용하지 않았을 때

UseForm을 사용하지 않을 때의 회원가입 코드는 다음과 같이 복잡하게 작성했었다. 아래는 상태이상관리를 사용하지 않았어서 state를 남발하는 코드를 보여줬었다.

import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";

const Create = () => {
  const navigate = useNavigate();
  ////엄청나게 많은 useState들..
  const [isEmail, setIsEmail] = useState(false);
  const [isNumber, setIsNumber] = useState(false);
  const [isPassword, setIsPassword] = useState(false);
  const [passwordMessage, setPasswordMessage] = useState("");
  const [emailMessage, setEmailMessage] = useState("");
  const [state1, setState1] = useState(false);
  const [state2, setState2] = useState(false);
  const [theme, setTheme] = useState(localStorage.getItem("theme"));
  useEffect(() => {
    localStorage.setItem("theme", theme);
    document.body.className = theme;
  }, [theme]);
  const handleInputId = (e) => {
    setInputId(e.target.value);
    if (e.target.value.length < 2 || e.target.value.length > 8) {
      setIsId(false);
    } else {
      setIsId(true);
    }
    //-------------------생략---------------------
    const onChangePassword = (e) => {
    setInputPw(e.target.value);
    const passwordRegExp =
      /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,25}$/;
    if (!passwordRegExp.test(inputPw)) {
      setPasswordMessage(
        "숫자+영문자+특수문자 조합으로 8자리 이상 입력해주세요!"
      );
    } else {
      setPasswordMessage("안전한 비밀번호 입니다.");
      setIsPassword(true);
    }
  };
  return (
    <div className={`${theme}`}>
      <h1 class="my-5 py-2 text-xl text-center">회원가입</h1>
      <h2 class="px-10 text-lg font-semibold buri">계정</h2>
      <div class="py-5 flex justify-center">
        <input
          class="rounded text-sm border-b-2 w-1/2 leading-loose bg-transparent border-[#989898]"
          placeholder="이메일을 입력해주세요"
          type="text"
          name="input_email"
          value={inputEmail}
          onChange={handleInputEmail}
        />
        <button
          onClick={onChangeEmail}
          class="ml-2 text-center border rounded-full text-red-300 w-1/4 border-red-300 dark:bg-[#323435]"
        >
          인증번호 전송
        </button>
        //-----------생략-------------

이때는 깔끔하지 못한 코드를 적었었고 유효성도 각각 함수를 만들어서 state에 값을 넣는 비효율적인 방식을 사용했었다.🥺

3.UseForm 초기세팅

react-hook-form패키지로부터 useForm() 훅(hook)함수를 불러온 후, 컴포넌트 함수안에서 이 함수를 호출하는 형식이다.

useForm()에는 여러 return props를 가지고 있는데 그 중 register과 formState, watch, setValues를 이용했다. 초기세팅은 다음과 같이 진행했다.

🚨유의점 : 해당코드는 tsx형식으로 작성되었다.
또한 handleSubmit을 보통 많이 사용하지만 axios사용시 서버와의 에러로 인해서 다른 방식으로 넘기게 되었다. handleSubmit을 활용하여 fetch방식으로 넘겨서 작동이 잘 되었던 코드는 로그인 게시글 때 올릴 예정이다.

interface UserValue {
  email: string;
  password: string;
  nickname: string;
  passwordConfirm: string;
  idCheck: boolean;
  emailCheck: boolean;
  numberCheck: boolean;
}
function CreatePage() {
  const regExpEm =
    /^[A-Za-z0-9_]+[A-Za-z0-9]*[@]{1}[A-Za-z0-9]+[A-Za-z0-9]*[.]{1}[A-Za-z]{1,3}$/;
  const regExgPw = /^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,25}$/;

  const {
    register,
    watch,
    setValue,
    formState: { errors, isValid },
  } = useForm<UserValue>({
    mode: "onChange",
  });
}
Fuction내용
registerinput 요소를 React hook form과 연결시켜줌으로써,
검증 규칙을 적용할 수 있게 하는 메소드이다.
watchform state에 관한 정보를 담고 있는 객체이다.
setValue지정된 입력을 읽고, 해당 값을 반환한다.
입력 값을 렌더링하고 조건별로 무엇을 렌더링할지 결정하는 데 사용한다.
formState등록된 필드의 값을 동적으로 설정하고,
양식 상태를 확인하고 업데이트하는 기능이다.

해당 useForm은 onChange가 발생할 때 validation을 발생시키도록 하였다. mode는 useForm()에 넘겨줄 수 있는 다양한 optional arguments 중 하나로 사용자가 form을 submit 하기 전에 validation이 실행될 수 있게 해준다.

4.Input요소에 Validation과 함께 UseForm을 사용하기

      <LoginInputDiv>
        <CreateStyledInput
          placeholder="이메일을 입력해주세요"
          type="email"
          id="userEmail"
          required
          {...register("email", { required: true, pattern: regExpEm })}
        />
        <CreateStyledInputButton onClick={emailCheck}>
          인증번호 전송
        </CreateStyledInputButton>
      </LoginInputDiv>
      {errors.email?.type === "required" && (
        <ErrorDiv>이메일을 입력해주세요</ErrorDiv>
      )}
      {errors.email?.type === "pattern" && (
        <ErrorDiv>잘못된 이메일 형식입니다</ErrorDiv>
      )}
//....

register 메소드를 사용해서 input 요소를 React hook form에 등록해준다. 이 때 validation도 같이 시행해주기 위해서 필수 항목 입력을 하게 해주는 required와 유효성 검사를 도와주는 pattern을 활용하였다.

required ? 입력에 값이 있어야 양식을 제출할 수 있음을 나타내는 boolean이다. 오류 개체에서 오류 메시지를 반환하는 문자열을 할당할 수 있다.
pattern ? 입력에 대한 정규식 패턴을 넣을 수 있다.

이 이외에도 maxLength, minLength 등 다른 방법도 있고 validate을 직접 만들어줄 수 있다.

5.Server에 react hook form props 전달하기

🚨문제점🚨 : 기존에 사용했던 fetch가 아닌 axios로 바꿔서 API를 보낸 결과, handleSubmit방식이 fetch에서는 되지만 axios에서는 500에러가 나는 문제가 존재했었다.
✅임시해결방법✅ : watch를 활용해서 값을 넘겨주었다. submit방식을 활용하지 못한 건 아쉽지만 axios를 이번 프로젝트에 도입할 것이기 때문에 오류를 일으키지 않는 방향으로 가기로 하였다.
handleSubmit방식은 Login에서 fetch방식으로 보여줄 예정이다. 이번 방식은 axios를 활용한 watch와 setValues의 사용방식을 보여줄 것이다.


  const emailCheck = (e: React.MouseEvent<HTMLButtonElement>) => {
    e.preventDefault();
    axios
      .post(
        "https://seohamserver.shop/mail/send",
        {
          email: watch("email"),
        },
        { headers: { "Content-Type": "application/json" } }
      )
      .then((res) => {
        if (res.status === 200) {
          window.alert("사용가능한 이메일입니다.인증번호를 보냈습니다");
          setValue("emailCheck", true);
        } else {
          window.alert("이미 사용중이거나 유효하지 않는 이메일입니다");
          setValue("emailCheck", false);
        }
      });
  };
//...
  const clickSignUp = (e: React.MouseEvent<HTMLButtonElement>) => {
    e.preventDefault();
    if (
      watch("emailCheck") === false ||
      watch("idCheck") === false ||
      watch("numberCheck") === false ||
      watch("password") !== watch("passwordConfirm")
    ) {
      alert("유효성 검사 및 비밀번호중복확인을 완료해주세요");
    } else {
      axios
        .post("${API주소}/user/join", {
          email: watch("email"),
          passWord: watch("password"),
          nickName: watch("nickname"),
        })
        .then((res) => {
          if (res.status === 200) {
            alert("가입이 완료되었습니다");
            navigate("/");
          } else {
            alert("조금 있다가 시도해주세요");
          }
        });
    }
  };
//.....
return(
  //.....
      <LongInputDiv>
        <LoginButton type="submit" disabled={!isValid} onClick={clickSignUp}>
          확인
        </LoginButton>
      </LongInputDiv>
)

6.완성된 모습

인증번호를 하기 위해서는 실제 이메일을 사용해야하기 때문에 나중에 로그인까지 완료가 되면 그 때 실행할 예정이다. 지금은 react hook form으로 register와 validation이 어떻게 이루어지는지를 보면 된다.😍

다음에는 Login부분을 handleSubmit방식과 함께 다룰 예정이다.


참고자료
https://react-hook-form.com
https://heokknkn.tistory.com/44
https://velog.io/@qhflrnfl4324/낑깡팜06-yoeewma5
profile
예비 초보 개발자의 프로젝트와 공부 기록일지

1개의 댓글

comment-user-thumbnail
2024년 10월 2일

감사합니다 배워갑니다! 좋은 한 주 되세요 ☺️

답글 달기