개발공부

[React Hook Form] 선택 이유와 사용법

떡볶이가 최고야 2024. 7. 12. 17:45

react-hook-form 이란?

폼 관리 라이브러리로, 간단하고 효율적인 방식으로 폼 유효성 검사와 상태 관리를 처리할 수 있게 도와줍니다.

 


이번 프로젝트에서 react-hook-form을 선택한 이유

1. 성능 최적화

react-hook-form은 내부적으로 성능 최적화를 고려하여 설계되었습니다. 특히 리렌더링을 최소화하여 빠른 사용자 경험을 제공합니다.

 

2. 간편한 사용

사용하기 쉽고 직관적인 api를 제공하여 필요한 기능을 Hook 함수로 호출하여 사용할 수 있습니다.

 

3. 유연성과 확장성

react-hook-form은 유연하고 확장 가능한 구조를 가지고 있습니다. 커스텀 컴포넌트와의 통합이 간단하여 제가 사용하려는 shadcn/ui 컴포넌트와의 사용에 적합하다고 생각했습니다.


기본적인 사용법

사용하기 위해 react-hook-form이 제공하는 기본적인 Hook과 사용법에 대해서 알아보겠습니다.

 

useForm : 폼 제어를 위해 제공되는 Hook

  • register : useForm 훅이 리턴하는 등록과 관련된 메소드. name, ref, onChange 등과 같은 항목들을 리턴합니다.
const SignUpForm = () => {
	const {register} = useForm();//폼 제어 Hook
    
    //register가 리턴하는 객체 항목을 input 항목과 연결시켜 사용
    const {name, ref, onChange, onBlur} = register("username");
    
    return(
    	<form>
        <div className="w-1/3">
          <label htmlFor="username">Username</label>
          <input
            type="text"
            id="username"
            //아래 코드를 {...register("username")}이렇게 줄일 수 있습니다.
            name={name}
            ref={ref}
            onChange={onChange}
            onBlur={onBlur}
          />
          ...
          ...
}

 

  • handleSubmit : useForm 훅이 리턴하는 핸들러 제어 함수.
const { handleSubmit } = useForm();

const  onSubmit = (data) => {
  console.log("Form submitted.", data)
}

  return (
      <form onSubmit={handleSubmit(onSubmit)}>
      ...
      ...

 

 

유효성 검증을 위해 제공하는 방법

register함수의 두 번째 인자로 객체의 형태로 넣어줍니다. 

  • required
  • minLength & maxLength
  • min & max
  • pattern
// noValidate로 HTML 기본 유효성 검증 기능을 꺼줍니다.
<form onSubmit={handleSubmit(onSubmit)} noValidate>
//required 사용 예시 : 폼의 필수요소로 지정하고 에러 메세지 등록하기
<input
  type='text'
  id='username'
  {...register('username', {
    required: 'Username is required.',
  })}
/>
//pattern 사용 예시
<input
  type='email'
  id='email'
  {...register('email', {
    pattern: {
      value:
        /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/,
      message: 'Email is invalid.',
    },
  })}
/>
//minLength 사용 예시 : 최소 길이 지정하기
<input
  type='password'
  id='password'
  {...register('password', {
    minLength: {
      value: 8,
      message: 'Password must be at least 8 characters.',
    },
  })}
/>

 

formState : 에러 메시지 표시하기 위한 객체

  const { formState } = useForm<FormValues>();
  const { errors } = formState;
  
  //축약형
  const { formState: { errors } } = useForm<FormValues>();
  
  
  //사용 예시
  <p>{errors.username?.message}</p>

 

validation 함수 : 유효성 검증 커스텀하기

"admin@fly.dev" 라는 이메일로는 가입을 하지 못하게 하기

OR(||) 연산자를 통해 앞의 조건이 false이면 다음 값인 에러 메세지를 리턴하도록 합니다.

<input
  type='email'
  id='email'
  {...register('email', {
    validate: fieldValue => {
      return fieldValue !== 'admin@fly.dev' || 'You can not use admin@fly.dev!'
    },
  })}
/>

 

defaultValues : input의 기본 값 지정하기

const {
  register,
  control,
  handleSubmit,
  formState: { errors },
} = useForm <
FormValues >
{
  defaultValues: {
    username: 'IU',
    email: '',
    password: '',
  },
}

 

watch : 실시간으로 FormValues 감시하기

사용자가 입력하고 있는 값을 실시간으로 감시할 수 있습니다.

리렌더링을 방지하기 위해서 useEffect 함수 안에 subscription, unsubscribe 방식으로 사용합니다.

//편의상 다른 요소들(register,handleSubmit 등)은 생략했습니다.
const {watch} = useForm<FormValues>();

useEffect(() => {
    const subscription = watch(value => {
    	console.log(value)
    })

	return () => subscription.unsubscribe()
}, [watch])

 

getValues, setValues 함수 : FormValues 직접 제어하기

const {
  getValues,
  setValue
} = useForm <FormValues >();

const handleGetValues = () => {
  console.log("Values", getValues());
}

const handleSetValue = () => {
    setValue("username", "", {
      shouldValidate: true,
      shouldDirty: true,
      shouldTouch: true,
    });
}

...
...

return (
...
...
<button>Submit</button>
<button type="button" onClick={handleGetValues}>getValues</button>
<button type="button" onClick={handleSetValue}>setValue</button>
...
...
)