본문으로 건너뛰기

useForm

</> useForm: UseFormProps

useForm은 폼을 쉽게 관리하기 위한 사용자 정의 훅입니다. 하나의 객체를 선택적 인수로 받습니다. 다음 예제는 모든 속성과 기본값을 보여 줍니다.

일반 속성:

옵션설명
mode제출 동작을 위한 검증 전략입니다.
reValidateMode제출 동작을 위한 검증 전략입니다.
defaultValues폼의 기본값입니다. 이 값은 캐시됩니다.
values폼 값을 갱신할 반응형 값입니다.
errors서버에서 반환된 오류로 폼을 갱신합니다. ⚠ 중요: 무한 리렌더링을 방지하려면 errors 객체의 참조를 안정적으로 유지합니다.
resetOptions새 폼 값으로 갱신할 때 폼 상태를 초기화하는 옵션입니다.
criteriaMode모든 검증 오류를 표시하거나 한 번에 하나만 표시합니다.
shouldFocusError내장 포커스 관리를 활성화하거나 비활성화합니다.
delayError오류가 즉시 나타나지 않도록 지연합니다.
validate폼 수준 검증은 내장 검증 메서드로 제한됩니다.
shouldUseNativeValidation브라우저의 내장 폼 제약 조건 API를 사용합니다.
shouldUnregister언마운트 후 입력의 등록 해제를 활성화하거나 비활성화합니다.
progressive검증 속성(required, min, max 등)을 입력의 네이티브 HTML 속성으로 전달합니다. Form 컴포넌트의 점진적 향상을 활성화합니다(하이드레이션/JS 로드 전에도 사용할 수 있는 HTML).
disabled연결된 모든 입력과 함께 전체 폼을 비활성화합니다.
formControl미리 생성한 폼 control 객체(createFormControl에서 생성)를 제공하여 useForm이 내부에서 만들지 않도록 합니다.

스키마 검증 속성:

옵션설명
resolver선호하는 스키마 검증 라이브러리와 통합합니다.
context스키마 검증에 제공할 context 객체입니다.

속성


mode: onChange | onBlur | onSubmit | onTouched | all = 'onSubmit' ! React Native: Controller와 호환


이 옵션으로 폼 제출 전의 검증 전략을 구성할 수 있습니다. 검증은 onSubmit 이벤트에서 실행되며, 이 이벤트는 handleSubmit 함수를 호출하면 발생합니다.

이름타입설명
onSubmitstringsubmit 이벤트에서 검증이 실행되며, 입력에는 자체 재검증을 위한 onChange 이벤트 리스너가 연결됩니다.
onBlurstringblur 이벤트에서 검증이 실행됩니다.
onChangestring각 입력의 change 이벤트에서 검증이 실행되어 여러 번 리렌더링됩니다. 경고: 성능에 상당한 영향을 주는 경우가 많습니다.
onTouchedstring첫 번째 blur 이벤트에서 최초 검증이 실행됩니다. 이후에는 모든 change 이벤트에서 실행됩니다.

참고: Controller와 함께 사용할 때는 onBlurrender 속성에 연결해야 합니다.
allstringblurchange 이벤트 모두에서 검증이 실행됩니다.

reValidateMode: onChange | onBlur | onSubmit = 'onChange' ! React Native: 사용자 정의 register 또는 Controller 사용


이 옵션으로 폼 제출 오류가 있는 입력을 다시 검증하는 전략을 구성할 수 있습니다(onSubmit 이벤트가 발생하고 handleSubmit 함수가 실행된 후). 기본적으로 입력 변경 이벤트에서 재검증이 실행됩니다.

참고: v7.56.0부터 modereValidateMode는 모두 반응형입니다. 폼 초기화 후에도 갱신할 수 있으며 새 전략은 이후 검증부터 적용됩니다.

defaultValues: FieldValues | () => Promise<FieldValues>


defaultValues 속성은 전체 폼을 기본값으로 채웁니다. 기본값을 동기 또는 비동기로 할당할 수 있습니다. defaultValue 또는 defaultChecked를 사용해 입력의 기본값을 설정할 수도 있지만(React 공식 문서 참고), 전체 폼에는 defaultValues를 사용하는 것이 권장됩니다.

useForm({
defaultValues: {
firstName: "",
lastName: "",
},
})

// set default value async
useForm({
defaultValues: async () => fetch("/api-endpoint").then((res) => res.json()),
})

values: FieldValues v7.41.0부터


values 속성은 변경에 반응해 폼 값을 갱신하므로 외부 상태나 서버 데이터로 폼을 갱신해야 할 때 유용합니다. values 속성은 defaultValues 속성을 덮어쓰지만, resetOptions: { keepDefaultValues: true }useForm에 설정한 경우는 예외입니다.

// set default value sync
function App({ values }) {
useForm({
values, // will get updated when values props updates
})
}

function App() {
const values = useFetch("/api")

useForm({
defaultValues: {
firstName: "",
lastName: "",
},
values, // will get updated once values returns
})
}

errors: FieldErrors v7.49.0부터


errors 속성은 변경에 반응해 서버 오류 상태를 갱신하므로 서버에서 반환한 오류로 폼을 갱신해야 할 때 유용합니다.

function App() {
const { errors, data } = useFetch("/api")

useForm({
errors, // will get updated once errors returns
})
}

resetOptions: KeepStateOptions v7.41.0부터


이 속성은 값 갱신 동작과 관련이 있습니다. valuesdefaultValues가 갱신되면 내부적으로 reset API가 호출됩니다. valuesdefaultValues가 비동기로 갱신된 이후 원하는 동작을 지정해야 합니다. 구성 옵션 자체는 reset 메서드의 옵션을 참조합니다.

// by default, an asynchronous update to values or defaultValues will reset the form values
useForm({ values })
useForm({ defaultValues: async () => await fetch() })

// options to configure the behavior
// eg: I want to keep user-interacted/dirty values and not remove any user errors
useForm({
values,
resetOptions: {
keepDirtyValues: true, // user-interacted input will be retained
keepErrors: true, // input errors will be retained with value update
},
})

context: object


이 context object는 변경할 수 있으며 resolver의 두 번째 인수 또는 Yup 검증의 context 객체에 주입됩니다.CodeSandbox 열기 ↗

criteriaMode: firstError | all


  • firstError(기본값)로 설정하면 각 필드의 첫 번째 오류만 수집합니다.
  • all로 설정하면 각 필드의 모든 오류를 수집합니다.
CodeSandbox 열기 ↗

shouldFocusError: boolean = true


true(기본값)로 설정하면 검증에 실패한 폼을 제출할 때 오류가 있는 첫 번째 필드에 포커스가 설정됩니다.

delayError: number v7.12.0부터


이 구성은 사용자에게 오류 상태를 표시하는 시점을 지정한 밀리초만큼 지연합니다. 사용자가 오류가 있는 입력을 수정하면 오류는 즉시 제거되고 지연은 적용되지 않습니다.CodeSandbox 열기 ↗

validate: Function v7.72.0부터


이 예제는 React 애플리케이션에서 validate APIuseForm과 함께 사용해 폼 수준 검증을 수행하는 방법을 보여 줍니다.

validate 함수는 { formValues, formState, eventType, name }을 받고 다음 중 하나를 반환해야 합니다. true(유효), string(formState.errors.form에 표시) 또는 { [fieldName]: { type, message } } 객체(각 항목이 formState.errors.form.<fieldName>에 표시)입니다. 참고: validateresolver가 구성되어 있으면 실행되지 않습니다. resolvervalidate는 상호 배타적이며 둘 다 설정하면 resolver만 실행됩니다.

예제:

const {
register,
formState: { errors },
} = useForm({
validate: async ({ formValues }) => {
if (formValues.test1.length > formValues.test.length) {
return {
test: {
type: "formError",
message: "something is wrong here",
},
}
}

if (formValues.test === "test") {
return "direct error message"
}

return true
},
})

shouldUnregister: boolean = false


기본적으로 입력이 제거되어도 해당 값은 유지됩니다. 하지만 shouldUnregistertrue로 설정하면 언마운트할 때 입력을 unregister할 수 있습니다.

  • 하위 수준 구성을 재정의하는 전역 구성입니다. 개별적으로 동작하게 하려면 useForm이 아니라 컴포넌트 또는 훅 수준에서 구성합니다.
  • 기본값인 shouldUnregister: false에서는 언마운트된 필드를 내장 검증으로 검증하지 않습니다.
  • shouldUnregisteruseForm 수준에서 true로 설정하면 제출 결과에 defaultValues가 병합되지 않습니다.
  • shouldUnregister: true로 설정하면 폼이 네이티브 폼과 유사하게 동작합니다.
    • 폼 값은 입력 자체에 저장됩니다.

    • 입력을 언마운트하면 해당 값이 제거됩니다.

    • 숨겨진 데이터를 저장하는 입력에는 hidden 속성을 사용해야 합니다.

    • 등록된 입력만 제출 데이터에 포함됩니다.

    • React Hook Form이 입력이 DOM에서 언마운트되었음을 확인할 수 있도록 useForm 또는 useWatchuseEffect에서 언마운트된 입력을 알려야 합니다.

      const NotWork = ({ register, show }) => {
      // ❌ won't get notified; you need to invoke unregister
      return show && <input {...register("test")} />
      }

      const Work = ({ control, register }) => {
      // "show" is itself a registered checkbox field in the same form
      const { show } = useWatch({ control })
      // ✅ gets notified in useEffect
      return show && <input {...register("test1")} />
      }

      const App = () => {
      const [showNotWork, setShowNotWork] = useState(false)
      const { register, control } = useForm({ shouldUnregister: true })
      return (
      <div>
      <input type="checkbox" {...register("show")} />
      {/* ✅ gets notified in useForm's useEffect */}
      {showNotWork && <input {...register("test2")} />}
      <NotWork register={register} show={showNotWork} />
      <Work control={control} register={register} />
      </div>
      )
      }

shouldUseNativeValidation: boolean = false v7.9.0부터


이 구성은 브라우저 네이티브 검증을 활성화합니다. CSS 선택자 :valid:invalid도 활성화되어 입력 스타일을 더 쉽게 지정할 수 있습니다. 클라이언트 측 검증이 비활성화되어 있어도 이 선택자를 사용할 수 있습니다.

  • onSubmitonChange 모드에서만 작동합니다. reportValidity가 실행되면 오류 입력에 포커스가 설정되기 때문입니다.

  • 네이티브로 표시하려면 등록된 각 필드의 검증 메시지가 문자열이어야 합니다.

  • 이 기능은 실제 DOM 참조에 연결된 register API와  useController/Controller에서만 작동합니다.

  • shouldUseNativeValidationprogressive와 독립적으로 작동합니다. 검증 속성이 네이티브 HTML 속성으로 전달되는지와 관계없이 React Hook Form이 계산한 검증 결과로 브라우저의 Constraint Validation API(setCustomValidity/reportValidity)를 직접 구동합니다. progressive와 함께 사용하면 SSR이나 하이드레이션 전 대체 검증 등을 위해 제약 조건 속성 자체(required, minLength 등)도 DOM에 표시할 수 있습니다.

    useForm({
    shouldUseNativeValidation: true,
    })
예제:

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

export default function App() {
const { register, handleSubmit } = useForm({
shouldUseNativeValidation: true,
progressive: true,
})
const onSubmit = async (data) => {
console.log(data)
}

return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
{...register("firstName", {
required: "Please enter your first name.",
})} // custom message
/>
<input type="submit" />
</form>
)
}

progressive: boolean = false v7.44.0부터


검증 규칙(required, min, max, minLength, maxLength, pattern)을 register에서 입력의 네이티브 HTML 속성으로 전달합니다. Form 컴포넌트의 점진적 향상을 활성화하여 하이드레이션 전에도 사용할 수 있는 HTML을 렌더링합니다. 이 옵션과 관계없이 React Hook Form 자체의 검증 결과로 브라우저 Constraint Validation API를 구동하는 shouldUseNativeValidation과는 독립적입니다. 제약 조건 속성도 DOM에 표시하려면 두 옵션을 함께 사용합니다.

useForm({
progressive: true,
})

disabled: boolean = false v7.48.0부터


이 구성을 true로 설정하면 전체 폼과 연결된 모든 입력을 비활성화할 수 있습니다.
비동기 작업 중 사용자 상호작용을 방지하거나 입력이 일시적으로 반응하지 않아야 하는 상황에 유용합니다.

예제:

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

const App = () => {
const [disabled, setDisabled] = useState(false)
const { register, handleSubmit, control } = useForm({
disabled,
})

return (
<form
onSubmit={handleSubmit(async () => {
setDisabled(true)
await sleep(100)
setDisabled(false)
})}
>
<input
type={"checkbox"}
{...register("checkbox")}
data-testid={"checkbox"}
/>
<select {...register("select")} data-testid={"select"} />

<Controller
control={control}
render={({ field }) => <input disabled={field.disabled} />}
name="test"
/>

<button type="submit">Submit</button>
</form>
)
}

resolver: Resolver


이 함수로 Yup, Zod, Joi, Vest, Ajv 등 다양한 외부 검증 라이브러리를 사용할 수 있습니다. 선호하는 검증 라이브러리를 원활하게 통합하는 것이 목적입니다. 라이브러리를 사용하지 않는 경우에도 폼 검증 로직을 직접 작성할 수 있습니다.

npm install @hookform/resolvers
매개변수

이름타입설명
valuesobject전체 폼 값을 담은 객체입니다.
contextobjectcontext 객체이며 useForm 구성에 제공할 수 있습니다. 리렌더링할 때마다 변경할 수 있는 가변 object입니다.
options
{
  "criteriaMode": "string",
  "fields": "object",
  "names": "string[]"
}
검증한 필드와 이름, criteriaModeuseForm의 정보를 담은 옵션 객체입니다.
예제:

import { useForm } from "react-hook-form"
import { yupResolver } from "@hookform/resolvers/yup"
import * as yup from "yup"

const schema = yup
.object()
.shape({
name: yup.string().required(),
age: yup.number().required(),
})
.required()

const App = () => {
const { register, handleSubmit } = useForm({
resolver: yupResolver(schema), // yup, joi and even your own.
})

return (
<form onSubmit={handleSubmit((d) => console.log(d))}>
<input {...register("name")} />
<input type="number" {...register("age")} />
<input type="submit" />
</form>
)
}

더 자세한 내용은 리졸버 문서를 참고하세요.

useForm 반환값과 useEffect 의존성

향후 메이저 릴리스에서는 useForm 반환값이 성능을 최적화하고 formState 변경을 반영하도록 메모이제이션됩니다. 이 변경이 적용되면 formState가 갱신될 때마다 반환 객체에 새 참조가 생깁니다. 따라서 이 객체를 useEffect 의존성 배열에 직접 넣으면 formState가 바뀔 때마다 effect가 다시 실행되며, effect 자체가 폼을 갱신하면(예: reset 호출) 무한 루프가 발생할 수 있습니다.

아래와 같이 관련 메서드만 전달하면 이러한 문제를 피할 수 있습니다.

const methods = useForm()

useEffect(() => {
methods.reset({ ... })
}, [methods.reset])

이 이슈에서 자세한 내용을 확인할 수 있습니다.

반환값


다음 목록은 useForm이 반환하는 속성의 참조 문서입니다.