react-hook-form을 활용해 효과적으로 form 관리하기

Eom Deokhyeon·2024년 1월 22일
0

📌 react-hook-form

react-hook-form은 React 기반의 폼 관리 라이브러리로, 폼 상태 관리폼 유효성 검사를 처리하기 위한 간단하고 효율적인 방법을 제공한다.

react-hook-form을 사용하면 폼 요소의 값이나 상태 변경에 대한 이벤트를 관리하기 위해 명시적인 이벤트 핸들러를 작성할 필요 없이, 단순히 hook만을 사용하여 폼 관련 데이터를 추적하고 업데이트할 수 있다.

📖 react-hook-form 장점

  1. 간편한 API
    react-hook-form은 사용하기 쉽고 직관적인 API를 제공하여 복잡한 폼 로직을 보다 단순하고 직관적이게 해준다. 필요한 기능을 간단히 훅 함수로 호출하고, 컴포넌트 내에서 필요한 상태와 메소드를 사용할 수 있다. 이를 통하여 개발자는 많은 부분을 직접 구현할 필요 없이 더욱 빠르고 효과적인 폼 개발에 집중할 수 있게 된다.

  2. 성능 최적화
    react-hook-form은 성능에 중점을 두어 최적화되어 있다. 입력 필드 값의 변화를 추적하는 "상태"대신 각 입력 필드의 참조를 사용하여 불필요한 리렌더링을 방지하고, 가상 DOM의 업데이트를 최소화한다. 이는 대규모 폼이나 복잡한 유효성 검사 로직이 필요한 폼에서 특히 유용하다.

  3. 유연성과 확장성
    react-hook-form은 자체적으로 유효성 검사를 지원하며, yup이나 joi 같은 외부 유효성 검사 라이브러리와 통합할 수도 있다. 또한 커스텀 훅을 사용하여 개발자가 필요한 로직을 보다 쉽게 작성하고 재사용할 수 있도록 지원한다.

📖 react-hook-form 주요 메소드

  • register : ref로 사용되는 함수로 입력 필드를 react-hook-form에 등록하고 변경 사항에 대해 값을 추적한다.

  • handleSubmit : form을 서버로 제출할 때 사용한다.

  • errors : 유효성 검사 실패 시 해당 필드의 에러 메시지를 포함한다.

  • setValue : 동적으로 입력 필드의 값을 설정할 수 있다. 에러가 발생하거나, 에러를 바로잡거나 할 때 렌더링 되어 불필요한 리렌더링을 피할 수 있다.

  • watch : 실시간으로 입력 필드에 입력된 값을 관찰하고 그 값을 반환한다. 렌더링 할 대상을 결정할 때 유용하다.

  • getValues : 입력 필드의 값을 읽을 때 사용한다. watch와는 다르게 리렌더링을 일으키거나 입력값의 변화를 구독하지 않는다.

  • control : Controller 컴포넌트를 사용하기 위해 만들어 졌다. 제어되는 컴포넌트를 react-hook-form에 등록하기 위한 메소드가 포함되어 있다.

  • formState : 말 그대로 폼 상태에 관한 객체로 폼에서 발생한 에러나 제출 여부, 값 유효성 등의 세부적인 상태를 확인할 수 있다.

📖 react-hook-form 유효성 검사

  • required : 필수 여부
  • min : 최소값
  • max : 최대값
  • minLength : 문자열 최소 길이
  • maxLength : 문자열 최대 길이
  • pattern : 정규식 검사
  • validate : 직접 작성한 유효성 검사 함수

💡 react-hook-form 간단 구현 예시

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

const Example = () => {
  const { register, handleSumbit } = useForm();

  const onSubmit = (data) => {
    console.log(data);
    // 회원가입 로직...
  }
  
  const onError = (error) => {
    if (error?.email) {
      return alert(error?.email?.message);
    } else if (error?.password) {
      return alert(error?.password?.message);
    } else if (error?.name) {
      return alert(error?.name?.message);
    } else if (error?.phone) {
      return alert(error?.phone?.message);
    }
  }
  
  return (
    <div>
      <div>
        <label>이메일</label>
    	<input 
    		{...register("email", {
              required: "이메일을 입력해 주세요.",
    		  pattern: {
    		    value: RegExp(/^[a-zA-Z0-9+-\\_.]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$/),
    		    message: "이메일 형식에 맞게 입력해 주세요."
    		  }
    		})} 
  		/>
      </div>
	  <div>
        <label>비밀번호</label>
    	<input 
		  type="password"
		  {...register("passowrd", {
            required: "비밀번호를 입력해 주세요.",
            pattern : {
              value: /^.*(?=^.{8,20}$)(?=.*\d)(?=.*[a-zA-Z])(?=.*[\x20-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]).*$/i,
              message: "비밀번호 형식에 맞게 입력해 주세요."
            },
            minLength: {
              value: 8,
              message: "비밀번호는 8자 이상으로 입력해 주세요.",
            },
          })} 
		/>
      </div>
      <div>
    	<label>이름</label>
    	<input {...register("name", { required: "이름을 입력해 주세요." })} />
      </div>
	  <div>
        <label>휴대폰번호</label>
        <input {...register("phone", { required: "휴대폰번호를 입력해 주세요." })} />
      </div>
      <button onClick={handleSubmit(onSubmit, onError)}>회원가입</button>
    </div>
  )
};

0개의 댓글

관련 채용 정보