[React Hook Form]

찐새·2022년 5월 11일
1

next.js

목록 보기
6/41
post-thumbnail
post-custom-banner

React Hook Form

Set up

# 지원하는 리액트 버전일 때
npm i react-hook-form

# 지원하지 않는 리액트 버전일 때
npm i react-hook-form --legacy-peer-deps

일반 form

리액트에서 일반 폼을 작성하려면 신경 쓸 부분이 많다. 각 input 값에 대한 useStateonChange를 작성하고, submit에서는 여러 검증 작업 코드를 넣어야 한다. 사용자가 필수 사항을 제대로 입력했는지, 양식에 맞게 작성했는지 등등. 검증에 적합하지 않을 시 보여줄 error에 대한 useState도 남았다. 사용자 경험을 만족시키려는 form을 만들기 위해서는 매우 복잡한 절차를 거쳐야 한다.

import React, { useState } from "react";

export default function Forms() {
  const [email, setEmail] = useState("");
  const [pwd, setPwd] = useState("");
  const [formErrors, setFormErrors] = useState("");
  const [emailErrors, setEmailErrors] = useState("");
  const [pwdErrors, setPwdErrors] = useState("");

  const onEmailChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
    const {
      currentTarget: { value },
    } = e;
    setEmailErrors("");
    setEmail(value);
  };
  const onPwdChange = (e: React.SyntheticEvent<HTMLInputElement>) => {
    const {
      currentTarget: { value },
    } = e;
    setPwdErrors("");
    setPwd(value);
  };
  const onSubmit = (e: React.SyntheticEvent<HTMLFormElement>) => {
    e.preventDefault();
    if (email === "" || pwd === "") {
      setFormErrors("빈 값이면 안 된다.");
    }
    if (!email.includes("@")) {
      setEmailErrors("이메일은 @를 포함해야 한다.");
    }
    if (pwd.length < 8) {
      setPwdErrors("비밀번호는 8자리 이상!");
    }
  };
  return (
    <form onSubmit={onSubmit}>
      <input
        value={email}
        onChange={onEmailChange}
        type="email"
        placeholder="Email"
        required
      />
      {emailErrors}
      <input
        value={pwd}
        onChange={onPwdChange}
        type="password"
        placeholder="Password"
        required
      />
      <input type="submit" value="Create Account" />
      {formErrors}
    </form>
  );
}

간단하게 이메일과 비밀번호만 입력하는 폼임에도 코드가 많이 길어졌다. 여기에 CSS 작업이나 기타 다른 검증 및 입력 요소를 추가한다면 코드는 매우매우 길어지고 복잡해질 것이다.

useForm

register

React Hook FormuseForm을 사용하면 기나긴 state 코드를 축약할 수 있다.

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

export default function Forms() {
	const { register } = useForm();
  return (
    <form>
      <input
    	{...register("email")}
        type="email"
        placeholder="Email"
        required
      />
      <input
		{...register("password")}
        type="password"
        placeholder="Password"
        required
      />
      <input type="submit" value="Create Account" />
    </form>
  );
}

const { register } = useForm(); 단 한 줄로 onChangevalue를 대신한다.
form에 어떤 값이 입력되었는지 보려면 watch 메서드를 사용한다.

const { watch } = useForm();
console.log(watch());

Validation

html의 required는 빈 입력을 막아주지만, 검사 내에서 속성을 지우거나 해당 속성을 지원하지 않는 브라우저에서는 동작하지 않는다. 때문에 Javascript내에서 작동하는 것이 안전하다.

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

export default function Forms() {
	const { register, /handleSubmit/ } = useForm();
    const onValid = () => {
    	console.log("유효옷!");
  	};
  	const onInvalid = () => {
    	console.log("무효옷!");
  	};
  return (
    <form onSubmit={handleSubmit(onValid, onInvalid)}>
      <input
    	{...register("email", /{required: true}/)}
        type="email"
        placeholder="Email"
        required
      />
      <input
		{...register("password", /{required: true}/)}
        type="password"
        placeholder="Password"
        required
      />
      <input type="submit" value="Create Account" />
    </form>
  );
}

/로 묶은 부분이 입력 상태를 확인하는 부분이다. {required: true}는 빈 입력을 허용하지 않는다.

handleSubmit은 form의 submit을 관리하는 함수로, 기본적으로 event.preventDefault() 기능을 가지면서 2개의 함수 인자를 받는다. onValidonInvalid로, 전자는 form이 유효할 때 동작하고, 후자는 유효하지 않을 때 동작한다. 이 함수들은 register에 입력되어 있는 규칙에 따른다. 위의 예로, 만약 내용이 없는 form을 제출한다면, "무효옷!"이 출력될 것이다. 모두 입력했다면 "유효옷!"이 출력된다.

typescript를 사용한다면 데이터 타입을 정할 수 있다.

interface LoginForm {
  password: string;
  email: string;
}

export default function Forms() {
  const { register, handleSubmit, /formState: { errors }/ } = useForm<LoginForm>();
  const onValid = (data: LoginForm) => {
    console.log("im valid");
  };
  const onInvalid = (errors: FieldErrors) => {
    console.log("im invalid");
  };
  return (
    <form onSubmit={handleSubmit(onValid, onInvalid)}>
  		{...children}
		{errors.email?.message}
    </form>
  );
}

발생한 에러를 화면에 표시할 때는 formState: { errors }를 이용한다.

유효성 검사 규칙

// reqired
required: "이메일은 필수 입력 사항입니다.",
// minLength
minLength: {
            message: "이름은 최소 2글자 이상이어야 합니다.",
            value: 2,
          },
// maxLength
maxLength: {
            message: "이름은 최대 5글자 이하여야 합니다.",
            value: 5,
          },            
// validation
validate: {
            notMail: (value) =>
              /[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,3}$/.test(value) || "이메일 양식을 지켜라",
          },            

mode

useForm이 지원하는 프로퍼티 중 mode는 form 제출 전에 유효성 검사를 실행한다.

  • onBlur는 입력이 끝난 양식이 규칙에 맞지 않을 경우 곧장 실행되고, 수정되면 바로 지워진다.
  • onChange는 form이 변할 때마다 규칙을 검사한다.

이 외의 유용한 api는 useForm | React Hook Form에서 확인 가능하다.


참고
노마드 코더 - 캐럿마켓 클론코딩
React Hook Form

profile
프론트엔드 개발자가 되고 싶다
post-custom-banner

0개의 댓글