[TS] react-hook-form을 이용하여 회원가입 구현해보기 👩‍💻

Beanxx·2022년 11월 27일
0

React

목록 보기
3/5
post-thumbnail

💡 react-hook-form이란?

form 관련 훅으로, 비제어 컴포넌트 방식으로 구현되어 있어 렌더링 이슈를 해결가능하다. 난 회원가입에서의 유저 정보들을 yup을 활용하여 구현한 유효성검사와 함께 react-hook-form을 적용해보았다.

아래 글에 왜 react-hook-form을 쓰면 좋은지 적용 과정과 함께 아주 잘 정리해놓으셨다! 🙌
🔗 [tech.inflab.com] react-hook-form을 선택한 이유와 적용 과정

일단 아래 명령어를 통해 react-hook-formyup을 설치해준다.

npm install react-hook-form yup @hookform/resolvers

import할 것도 챡챡 해주기!

// import해줄것!
import { useForm, SubmitHandler } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";

글구 form 유효성 검사를 해주는 yup을 활용하여 schema를 설정해준다. 나는 validation을 따로 hooks 폴더에 분리해주었다.

// validationYup.tsx

// yup schema 설정
const schema = yup.object().shape({
  name: yup
    .string()
    .min(3, "닉네임을 3글자 이상으로 입력해주세요.")
    .required("닉네임을 필수로 입력해주세요."),
  email: yup
    .string()
    .email("이메일 형식을 맞춰서 입력해주세요.")
    .required("이메일을 필수로 입력해주세요."),
  password: yup
    .string()
    .min(3, "비밀번호를 3~16글자로 입력해주세요.")
    .max(16, "비밀번호를 3~16글자로 입력해주세요.")
    .matches(
      /^(?=.*[a-zA-Z])((?=.*\d)(?=.*\W))/,
      "비밀번호에 영문, 숫자, 특수문자를 포함해주세요."
    )
    .required("비밀번호를 필수로 입력해주세요."),
  confirmPassword: yup
    .string()
    .oneOf([yup.ref("password"), null], "비밀번호가 일치하지 않습니다."),
});

react-hook-form 적용은 공식문서에 TS로 적용하는 방법도 잘 나와있기 때문에 그거 고대로 따라하면 된다~!

// 타입 지정
type Inputs = {
  name: string;
  email: string;
  password: string;
  confirmPassword: string;
};

// react-hook-form 적용하여 회원가입폼 구현하기
const JoinForm = () => {
  const {
    register,
    handleSubmit,
	reset, // 필드값 초기화
    formState: { isSubmitting, errors },
  } = useForm<Inputs>({ resolver: yupResolver(schema), mode: "onChange"});
	// 여기서 mode: "onChange"를 써줘야 값이 바뀔 때마다 유효성 검사를 해준다! 

  const onSubmit: SubmitHandler<Inputs> = async (data) => {
    console.log(data);
  };

  return (
    <Container>
	  {/* handleSubmit() 이용시 새로고침 현상 X => e.preventDefualt() 설정 필요없다! */}
      <Form id="join" onSubmit={handleSubmit(onSubmit)}>
        <LoginInput id="name" type="text" register={register("name")}>
          NickName
        </LoginInput>
        {errors.name && <Message>{errors.name.message}</Message>}
	    ...
	    {/* disabled 속성으로 isSubmitting 값을 주면 폼 제출이 완료 되기 전에는 버튼 비활성화해줌! */}
        <BasicBtn disabled={isSubmitting} type="submit">
          Sign up
        </BasicBtn>
      </Form>
    </Container>
  );
};


🚨 Error Handling

👀 분리한 Input 컴포넌트에 react-hook-form 적용

구현하는 과정에서 좀 애먹었던 내용쓰,, 그냥 input 태그에 적용하면 잘 되는데 재사용을 위해 따로 분리해두었던 Input 컴포넌트를 사용시 값이 잘 안 넘어가서 data 값이 undefined가 뜨는 바람에 에러 메세지 또한 출력이 되지 않았다,,🥲
폭풍구글링을 통해 아래 블로그 글을 참고했더니 드뎌 잘 작동됨~! 🥳

🔗 [에러 해결 참고자료] react-hook-form과 React.forwardRef() 에러

분리한 Input 컴포넌트에서 forwardRef를 따로 적용한 후에 hook-form을 적용하는 부분인 {…register(’name’)} 이 값을 Input 컴포넌트로 넘겨줘야 하는데 이에 대한 타입을 UseFormRegisterReturn 으로 따로 지정해준다.
이후 여기서 input 속성으로 props.register를 불러오면 끄읏-

// LoginInput.tsx

import { UseFormRegisterReturn } from "react-hook-form";

interface InputType {
  children: React.ReactNode;
  id: string;
  type?: string;
}

interface Props extends InputType {
  register?: UseFormRegisterReturn;
}

const LoginInput = React.forwardRef((props: Props, ref) => {
  return (
    <input
      id={props.id}
      type={props.type}
      autoComplete="off"
      ref={ref}
      {...props.register}
    />
  );
});


💫 위의 과정을 통해 구현해본 간단 회원가입폼 컴포넌트!
🔗 react-hook-form & yup으로 구현한 회원가입폼 배포 링크

react-hook-form를 한번 적용해보는 과정이 수월하진 않았지만 한번 사용해봤으니까 다른 플젝에다가 가져다가 쓰면 무척이나 편리할 것 같은 느낌!
특히, 회원가입, 로그인 부분에서 value, onChange로 값 관리를 하지 않아도 된다는 점이 맘에 듬! 👏👏👏

profile
FE developer

0개의 댓글