Study/React

[React] React Hook Form

다니니니 2024. 11. 23. 16:10
728x90

들어가며

React Hook Form 은 비제어 컴포넌트를 기반으로 동작하는 폼 관리 라이브러리다.

React 에서 form 을 쉽게 관리할 수 있도록 해주며, form의 상태 관리와 유효성 검사를 간단하게 만들어준다.

 

React Hook Form

React Hook Form 은 다음의 커맨드로 설치할 수 있다.

npm install react-hook-form

 

React Hook Form 은 useForm 이라는 훅을 통해 폼 상태, 검증 및 제출 로직을 관리한다.

import { useForm } from 'react-hook-form'

 

React Hook Form 에서 주로 사용되는 메서드는 아래와 같다.

  • register : 입력 요소에 연결하기 위한 함수. 이 함수를 통해서 입력 요소에 유효성 검사 규칙을 설정할 수 있다
  • handleSubmit : 폼의 제출을 처리하기 위한 함수. 이 함수에 전달된 콜백은 유효성 검사를 통과한 데이터를 인자로 받아서 실행한다. 
  • watch :  특정 폼 필드의 값을 실시간으로 관찰하는 함수 
  • formState : 폼의 상태를 나타내는 객체 (ex. errors, isValid, isDirty, isSubmitted 등의 상태 포함)

 

예시 코드

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

const errorMsgStyle = {
  fontSize: "12px",
  color: "red",
};

export default function Form() {
  const {
    register, // input 할당, value 변경 감지
    handleSubmit, // form submit 시 호출
    formState: { errors }, // 폼 상태 객체
    watch, // 특정 폼 필드의 값을 실시간으로 사용
  } = useForm();

  // handleSubmit(func A[, func B]) - 두개의 함수를 인자로 받는다. (두번째인자는 생략 가능)
  // func A는 필수 값, 유효할 때 실행
  // func B는 선택, 유효하지 않을 때 실행

  // func A -> 유효할 떄 실행
  const onValid = (data) => {
    console.log("onValid >>> ", data);
  };

  // func B -> 유효하지 않을 때 실행
  const onInValid = (err) => {
    console.log("onInValid >>> ", err);
  };

  console.log("errors>>>", errors);
  console.log("watch>>>", watch("username"));

  return (
    <div>
      <h1>react-hook-form 라이브러리 DEMO</h1>
      <form onSubmit={handleSubmit(onValid, onInValid)}>
        <div>
          <input
            type="text"
            placeholder="username"
            {...register("username", {
              required: "이름은 필수항목입니다.",
              minLength: {
                message: "이름은 최소 2글자 이상 작성해주세요",
                value: 2,
              },
            })}
            // 'username'이라는 필드명 / required, minLengh 라는 유효성 검사 규칙
            // 'username' 이라는 input 필드를 RHF(react-hook-form)에 등록
          />
          {errors.username && (
            <div style={errorMsgStyle}>{errors.username.message}</div>
          )}
        </div>
        {/* 이 표현은 조건부 렌더링과 옵셔널 체이닝을 활용하여 폼 필드의 오류 메시지를 표시하는 방법 */}
        {/* errors = formState 객체 중 하나 각 폼 필드에 대한 오류 메시지를 담고, 유효성 검사가 실패한 경우에만 해당 필드의 오류 메시지가 저장됨 */}
        {/* 옵셔널 체이닝 연산자 '?.'
                JS에서 객체의 속성에 접근할 때 해당 속성이 존재하는지 확인하고, 없을 경우 undefined 반환하는 연산자 */}

        <div>
          <input
            type="email"
            placeholder="email(gmail)"
            {...register("email", {
              required: "이메일을 입력해주세요",
              validate: {
                useGmail: (v) =>
                  v.includes("gmail.com") || "gmail로만 가입 가능합니다.",
              },
            })}
          />
          {/* validate : reat hook form 에서 제공하는 유효성 검사 옵션 중 하나,
                폼 필드에 대하 커스텀 유효성 검사를 수행할 수 있도록 함,
                함수 또는 함수들을 포함하는 객체를 받을 수 있음 */}
          {/* validate 가 객체로 사용될 경우, 객체의 각 속성에 대해 개별적인 유효성 검사 수행 가능
                각 속성은 함수 형태로 정의, 이 함수들이 개별적인 유효성 검사 규칙 적용 */}
          {/* 
                useGmail : validate 옵션의 객체 내부에서 useGmail 이라는 이름의 함수로 정의, 특정 유효성 검사 규칙 설정 
                v : 사용자가 email 필드에 입력한 값(이메일 주소)을 의미
            */}

          {errors.email && (
            <div style={errorMsgStyle}>{errors.email.message}</div>
          )}
        </div>
        <div>
          <input
            type="password"
            placeholder="password"
            {...register("password", {
              required: "비밀번호를 입력해주세요",
              pattern: {
                value: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{2,8}$/,
                message: "2~8글자의 영어+숫자 조합으로 입력해주세요",
              },
            })}
          />
          {/* pattern 을 사용해서 정규식으로 유효성 검사 가능 */}
          {errors.password && (
            <div style={errorMsgStyle}>{errors.password.message}</div>
          )}
        </div>
        <button type="submit">Submit</button>
      </form>
    </div>
  );
}

 

결과

 

유효성 검사 및 폼 제출
폼 제출 결과

React Hook Form 의 특징

React Hook Form 은 비제어 컴포넌트 기반으로 동작하기 때문에

폼 필드가 업데이트 될 때마다 전체 폼이 리렌더링 되지는 않는다.

이로 인해 불필요한 렌더링을 줄이고, 결과적으론 앱성능을 향상시킬 수 있다.

즉, 최적화에 적합하다.

 

또한, HTML5 의 기본적인 검증 속성인 required, minLength, maxLength 등을 사용할 수 있어,

검증 로직을 쉽고 간편하게 구현할 수 있다.

또, error 등 상태를 나타낼 수 있는 객체를 사용해서 간단하게 에러 메시지를 관리할 수 있다.

 

React Hook Form 의 동작 방식

앞서, React Hook Form 은 비제어 컴포넌트 기반으로 동작한다고 했다.

그래서 input 이나 form 의 값을 react state 에서 직접 관리하는 것이 아니라, 브라우저의 DOM 상태를 참조한다.

 

이로 인해 최소한의 리렌더링을 하여 성능을 향상 시킬 수 있다.

 

register 함수가 input 요소를 등록해서 DOM 참조를 생성하고, 이를 통해 값을 관리한다.

상태 관리는 폼 제출, 유효성 검사 시점에서 이루어진다.

 

React Hook Form 과 일반 Form 작성 비교

일반 Form

  • 각 입력 필드의 상태를 useState 로 관리해야함
  • 값이 바뀔 때마다 전체 컴포넌트가 리렌더링 될 수 있다.
  • 검증 로직을 직접 다 작성해야한다.
  • 폼 제출 시 각 입력 필드의 상태들을 모아서 폼 데이터를 수집해야 한다.

React Hook Form

  • useForm이라는 단일 훅을 이용해서  폼 상태, 검증 및 제출 로직을 관리하므로, 사용법이 직관적이고 코드가 간결하다.
  • 비제어 컴포넌트 기반으로 동작하여 필요한 경우에만 리렌더링 한다.
  • 다양한 검증 규칙을 쉽게 설정할 수 있다
  • handleSubmit 함수 하나로 모든 폼 데이터를 쉽게 관리할 수 있다.

이를 표로 정리하면 다음과 같다.

 

특징 일반 Form React Hook Form
상태 관리 React State 로 직접 관리 비제어 컴포넌트를 사용하여 상태를 DOM 에서 관리
유효성 검사 별도의 검증 로직을 작성 register 등을 사용해서 간단하게 구현 가능
리렌더링 입력값 변경 시마다 리렌더링 발생 비제어 컴포넌트 기반으로 리렌더링 최소화
코드 복잡도 state 관리 및 이벤트 핸들러로 인해 코드가 길어질 수 있음 간결한 코드로 작성 가능
성능 대규모 폼 양식 작성 시 성능 저하 문제 발생할 수 있음 최소한의 리렌더링으로 인한 성능 향상

 

 

따라서 일반 Form 양식은 간단한 폼 양식 작성 시에 사용하기 적합하고

React Hook Form 복잡하고 대규모 폼 양식을 작성할 떄 사용하기 적합하다.

(ex. 회원가입/로그인 폼 등)

 

따라서 리액트 프로젝트에서 form 을 사용할 일이 있으면 

프로젝트의 규모, form 을 사용하는 곳의 규모를 생각해서 적절한 것을 사용하면 되겠다.

Reference

코딩온 교안 자료

 

 

 

728x90