본문 바로가기
React

[React] React Hook Form

by D.B_18 2025. 10. 1.
공식 문서

 

react-hook-form은 유효성 검사를 쉽게 할 수 있는, 성능이 우수하고 유연하며 확장 가능한 form을 제공하는 라이브러리입니다.

설치

npm install react-hook-form

사용 예시

import { useForm, SubmitHandler } from "react-hook-form"

type Inputs = {
  example: string
  exampleRequired: string
}

export default function App() {
  const {
    register,
    handleSubmit,
    watch,
    formState: { errors },
  } = useForm<Inputs>()
  const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data)

  console.log(watch("example")) // watch input value by passing the name of it

  return (
    /* "handleSubmit" will validate your inputs before invoking "onSubmit" */
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* register your input into the hook by invoking the "register" function */}
      <input defaultValue="test" {...register("example")} />

      {/* include validation with required or other standard HTML validation rules */}
      <input {...register("exampleRequired", { required: true })} />
      {/* errors will return when field validation fails  */}
      {errors.exampleRequired && <span>This field is required</span>}

      <input type="submit" />
    </form>
  )
}
  • register : form에 input 등록하는 역할. 첫번째 인자로 들어가는 name 값으로 값을 제어합니다.
  • handleSubmit : form에 등록된 input들의 validation 체크를 수행합니다. onSubmit 메소드를 인자로 넘깁니다.
  • watch : form에 등록된 input들의 value들을 추적합니다. 인자값으로 name을 넘기면 특정 value만 조회합니다.
  • formState : form에서 관리되는 상태값들의 validation 결과. ex. errors, isValid, isDirty
 

💡 register가 안되는 라이브러리 컴포넌트 사용시 <Controller> 활용

기본적으로 input을 form에 등록할때 {…register('name')} 방식으로 등록합니다.

mui 같은 라이브러리 컴포넌트의 경우 ref 컴포넌트가 아닌 경우에 위의 방식으로 등록하여 사용하기 어렵습니다.

그럴때 <Controller>를 사용하여 form에 등록할 수 있습니다.

import { useForm, Controller, SubmitHandler } from "react-hook-form"
import { TextField, Checkbox } from "@material-ui/core"

interface IFormInputs {
  TextField: string
  MyCheckbox: boolean
}

function App() {
  const { handleSubmit, control, reset } = useForm<IFormInputs>({
    defaultValues: {
      MyCheckbox: false,
    },
  })
  const onSubmit: SubmitHandler<IFormInputs> = (data) => console.log(data)

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="MyCheckbox"
        control={control}
        rules={{ required: true }}
        render={({ field }) => <Checkbox {...field} />}
      />
      <input type="submit" />
    </form>
  )
}

hooks API 사용시

import * as React from "react"
import { useForm, useController, UseControllerProps } from "react-hook-form"

type FormValues = {
  FirstName: string
}

function Input(props: UseControllerProps<FormValues>) {
  const { field, fieldState } = useController(props)

  return (
    <div>
      <input {...field} placeholder={props.name} />
      <p>{fieldState.isTouched && "Touched"}</p>
      <p>{fieldState.isDirty && "Dirty"}</p>
      <p>{fieldState.invalid ? "invalid" : "valid"}</p>
    </div>
  )
}

export default function App() {
  const { handleSubmit, control } = useForm<FormValues>({
    defaultValues: {
      FirstName: "",
    },
    mode: "onChange",
  })
  const onSubmit = (data: FormValues) => console.log(data)

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Input control={control} name="FirstName" rules={{ required: true }} />
      <input type="submit" />
    </form>
  )
}

💡 배열로 form value를 관리하고 싶을때 useFieldArray

useFieldArray Docs

 

배열로 값을 관리하고 싶을 경우 useFieldArray를 사용할 수 있습니다.

function FieldArray() {
  const { control, register } = useForm();
  const { fields, append, prepend, remove, swap, move, insert } = useFieldArray({
    control, // control props comes from useForm (optional: if you are using FormProvider)
    name: "test", // unique name for your Field Array
  });

  return (
    {fields.map((field, index) => (
      <input
        key={field.id} // important to include key with field's id
        {...register(`test.${index}.value`)} 
      />
    ))}
  );
}
반응형