</> useForm:
UseFormProps
useForm
은 폼 관리를 쉽게 할 수 있도록 도와주는 커스텀 훅입니다. 이 훅은 선택적 인자로 하나의 객체를 받습니다. 아래 예제는 모든 속성과 기본값을 보여줍니다.
일반 속성:
옵션 | 설명 |
---|---|
mode | 제출 전 유효성 검사 전략. |
reValidateMode | 제출 후 유효성 검사 전략. |
defaultValues | 폼의 기본값. |
values | 폼 값을 업데이트하는 반응형 값. |
errors | 폼 오류를 업데이트하는 반응형 오류. |
resetOptions | 새로운 폼 값을 업데이트할 때 폼 상태를 초기화하는 옵션. |
criteriaMode | 모든 유효성 검사 오류를 한 번에 표시할지, 하나씩 표시할지 결정. |
shouldFocusError | 내장된 포커스 관리 기능을 활성화 또는 비활성화. |
delayError | 오류가 즉시 나타나지 않도록 지연. |
shouldUseNativeValidation | 브라우저 내장 폼 제약 API 사용 여부. |
shouldUnregister | 언마운트 후 입력 필드 등록 해제 여부. |
disabled | 폼과 관련된 모든 입력 필드를 비활성화. |
스키마 유효성 검사 속성:
Props
mode: onChange | onBlur | onSubmit | onTouched | all = 'onSubmit' React Native: Controller와 호환 가능
이 옵션은 사용자가 폼을 제출하기 전에 유효성 검사 전략을 설정할 수 있게 해줍니다. 유효성 검사는 handleSubmit
함수를 호출할 때 발생하는 onSubmit
이벤트 중에 이루어집니다.
이름 | 타입 | 설명 |
---|---|---|
onSubmit | string | submit 이벤트가 발생할 때 유효성 검사가 트리거되며, 입력 필드는 onChange 이벤트 리스너를 연결하여 스스로 재검증합니다. |
onBlur | string | blur 이벤트가 발생할 때 유효성 검사가 트리거됩니다. |
onChange | string | 각 입력 필드의 change 이벤트가 발생할 때마다 유효성 검사가 트리거되어 여러 번의 리렌더링이 발생합니다. 경고: 이 옵션은 성능에 큰 영향을 미칠 수 있습니다. |
onTouched | string | 처음 blur 이벤트가 발생할 때 유효성 검사가 트리거됩니다. 이후에는 모든 change 이벤트가 발생할 때마다 유효성 검사가 트리거됩니다.참고: Controller 와 함께 사용할 때는 render prop에 onBlur 를 연결해야 합니다. |
all | string | blur 와 change 이벤트 모두에서 유효성 검사가 트리거됩니다. |
reValidateMode: onChange | onBlur | onSubmit = 'onChange' React Native: Custom register or using Controller
이 옵션은 폼 제출 후(onSubmit
이벤트와 handleSubmit
함수 실행 후) 오류가 있는 입력 필드가 다시 검증되는 전략을 설정할 수 있게 해줍니다. 기본적으로는 입력 변경 이벤트 중에 다시 검증이 이루어집니다.
defaultValues: FieldValues | () => Promise<FieldValues>
defaultValues
prop은 폼 전체에 기본값을 채워줍니다. 동기 및 비동기 방식으로 기본값을 할당할 수 있습니다. defaultValue
나 defaultChecked
를 사용해 입력 필드의 기본값을 설정할 수 있지만 (공식 React 문서 참조), 전체 폼에 대해서는 defaultValues
를 사용하는 것을 권장합니다.
useForm({defaultValues: {firstName: '',lastName: ''}})// 비동기로 기본값 설정useForm({defaultValues: async () => fetch('/api-endpoint');})
-
undefined
를 기본값으로 제공하는 것은 피해야 합니다. 이는 제어 컴포넌트의 기본 상태와 충돌할 수 있습니다. -
defaultValues
는 캐시됩니다. 이를 초기화하려면 reset API를 사용하세요. -
defaultValues
는 기본적으로 제출 결과에 포함됩니다. -
Moment
나Luxon
과 같이 프로토타입 메서드를 포함한 커스텀 객체를defaultValues
로 사용하는 것은 권장하지 않습니다. -
폼 데이터를 포함하는 다른 방법도 있습니다:
// 숨겨진 입력 필드 추가<input {...register("hidden", { value: "data" })} type="hidden" />// onSubmit 시 데이터 포함const onSubmit = (data) => {const output = {...data,others: "others",}}
values: FieldValues
values
prop은 변경에 반응하여 폼 값을 업데이트합니다. 이는 폼이 외부 상태나 서버 데이터에 의해 업데이트되어야 할 때 유용합니다. values
prop은 useForm
에 resetOptions: { keepDefaultValues: true }
가 설정되지 않는 한, defaultValues
prop을 덮어씁니다.
// 기본값을 동기적으로 설정function App({ values }) {useForm({values, // values props가 업데이트될 때 함께 업데이트됨})}function App() {const values = useFetch("/api")useForm({defaultValues: {firstName: "",lastName: "",},values, // values가 반환되면 업데이트됨})}
errors: FieldErrors
errors
props는 변경에 반응하고 서버 오류 상태를 업데이트합니다. 이는 폼이 외부 서버에서 반환된 오류로 업데이트되어야 할 때 유용합니다.
function App() {const { errors, data } = useFetch("/api")useForm({errors, // errors가 반환되면 업데이트됩니다.})}
resetOptions: KeepStateOptions
이 속성은 값 업데이트 동작과 관련이 있습니다. values
또는 defaultValues
가 업데이트되면 내부적으로 reset
API가 호출됩니다. values
또는 defaultValues
가 비동기적으로 업데이트된 후 원하는 동작을 지정하는 것이 중요합니다. 이 설정 옵션은 reset 메서드의 옵션을 참조합니다.
// 기본적으로 비동기적으로 값 또는 defaultValues가 업데이트되면 폼 값이 초기화됩니다.useForm({ values })useForm({ defaultValues: async () => await fetch() })// 동작을 구성하는 옵션// 예: 사용자가 상호작용한/변경된 값을 유지하고 사용자 오류를 제거하지 않으려는 경우useForm({values,resetOptions: {keepDirtyValues: true, // 사용자가 상호작용한 입력값이 유지됩니다.keepErrors: true, // 값 업데이트 시 입력 오류가 유지됩니다.},})
context: object
이 context object 는 변경 가능하며, resolver 의 두 번째 인자나 Yup 검증의 context 객체에 주입됩니다. | CodeSandbox |
criteriaMode: firstError | all
| CodeSandbox |
shouldFocusError: boolean = true
이 값을 true
로 설정하면(기본값), 사용자가 유효성 검사에 실패한 폼을 제출할 때 첫 번째 오류가 발생한 필드에 포커스가 자동으로 이동합니다.
ref
가 등록된 필드만 이 기능이 동작합니다. 커스텀으로 등록된 입력 필드는 적용되지 않습니다. 예를 들어:register('test') // 동작하지 않음
- 포커스 순서는
register
순서를 기반으로 합니다.
delayError: number
이 설정은 지정된 밀리초(ms) 동안 오류 상태를 최종 사용자에게 표시하는 것을 지연시킵니다. 사용자가 오류 입력을 수정하면 오류가 즉시 제거되며, 지연 시간이 적용되지 않습니다. | CodeSandbox |
shouldUnregister: boolean = false
기본적으로 입력 필드가 제거되더라도 해당 입력 값은 유지됩니다. 하지만 shouldUnregister
를 true
로 설정하면 언마운트 시 입력 필드를 unregister
할 수 있습니다.
-
이 설정은 전역적으로 적용되며, 하위 레벨의 설정을 덮어씁니다. 개별적인 동작을 원한다면
useForm
이 아닌 컴포넌트나 훅 레벨에서 설정해야 합니다. -
기본값인
shouldUnregister: false
는 언마운트된 필드가 내장된 유효성 검사를 받지 않음을 의미합니다. -
useForm
레벨에서shouldUnregister
를true
로 설정하면,defaultValues
가 제출 결과와 병합되지 않습니다. -
shouldUnregister: true
로 설정하면 폼이 네이티브 폼과 더 유사하게 동작합니다.-
폼 값은 입력 필드 자체에 저장됩니다.
-
입력 필드가 언마운트되면 해당 값도 제거됩니다.
-
숨겨진 데이터를 저장하려면
hidden
속성을 사용해야 합니다. -
제출 데이터에는 등록된 입력 필드만 포함됩니다.
-
언마운트된 입력 필드는
useForm
또는useWatch
의useEffect
에서 알림을 받아야 훅 폼이 DOM에서 해당 입력 필드가 언마운트되었음을 확인할 수 있습니다.const NotWork = () => {const [show, setShow] = React.useState(false)// ❌ 알림을 받지 못함, unregister를 호출해야 함return show && <input {...register("test")} />}const Work = ({ control }) => {const { show } = useWatch({ control })// ✅ useEffect에서 알림을 받음return show && <input {...register("test1")} />}const App = () => {const [show, setShow] = React.useState(false)const { control } = useForm({ shouldUnregister: true })return (<div>// ✅ useForm의 useEffect에서 알림을 받음{show && <input {...register("test2")} />}<NotWork /><Work control={control} /></div>)}
-
shouldUseNativeValidation: boolean = false
이 설정은 브라우저의 기본 유효성 검사를 활성화합니다. 또한 :valid
와 :invalid
CSS 선택자를 사용할 수 있게 해 입력 필드 스타일링을 더 쉽게 만듭니다. 클라이언트 측 유효성 검사가 비활성화된 경우에도 이 선택자들을 사용할 수 있습니다.
onSubmit
및onChange
모드에서만 작동합니다.reportValidity
실행 시 오류가 발생한 입력 필드에 포커스가 이동하기 때문입니다.- 각 등록된 필드의 유효성 검사 메시지는 기본적으로 표시되기 위해 문자열이어야 합니다.
- 이 기능은 실제 DOM 참조와 연결된
register
API 및useController/Controller
에서만 작동합니다.
예제:
import { useForm } from "react-hook-form"export default function App() {const { register, handleSubmit } = useForm({shouldUseNativeValidation: true,})const onSubmit = async (data) => {console.log(data)}return (<form onSubmit={handleSubmit(onSubmit)}><input{...register("firstName", {required: "이름을 입력해주세요.",})} // 커스텀 메시지/><input type="submit" /></form>)}
disabled: boolean = false
이 설정을 true
로 설정하면 폼 전체와 관련된 모든 입력 필드를 비활성화할 수 있습니다.
이 기능은 비동기 작업 중이나 입력 필드가 일시적으로 반응하지 않아야 하는 상황에서 사용자 상호작용을 방지하는 데 유용합니다.
예제:
import { useForm, Controller } from "react-hook-form"const App = () => {const [disabled, setDisabled] = useState(false)const { register, handleSubmit, control } = useForm({disabled,})return (<formonSubmit={handleSubmit(async () => {setDisabled(true)await sleep(100)setDisabled(false)})}><inputtype={"checkbox"}{...register("checkbox")}data-testid={"checkbox"}/><select {...register("select")} data-testid={"select"} /><Controllercontrol={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
Props
이름 | 타입 | 설명 |
---|---|---|
values | object | 이 객체는 폼의 모든 값을 포함합니다. |
context | object | useForm 설정에서 제공할 수 있는 context 객체입니다. 이 객체는 리렌더링마다 변경 가능한 가변 객체입니다. |
options | { "criteriaMode": "string", "fields": "object", "names": "string[]" } | 이 옵션 객체는 useForm 에서 검증된 필드, 이름 및 criteriaMode 에 대한 정보를 포함합니다. |
- 스키마 검증은 필드 수준의 오류 보고에 중점을 둡니다. 부모 수준의 오류 검사는 그룹 체크박스와 같은 컴포넌트에 적용되는 직접적인 부모 수준으로 제한됩니다.
- 이 함수는 캐시됩니다.
- 사용자 상호작용 중에 입력 필드의 재검증은 한 번에 하나의 필드씩만 발생합니다. 라이브러리 자체가
error
객체를 평가하여 리렌더링을 적절히 트리거합니다. - 리졸버는 내장된 검증기(예: required, min 등)와 함께 사용할 수 없습니다.
- 커스텀 리졸버를 만들 때:
values
와errors
속성을 모두 가진 객체를 반환해야 합니다. 기본값은 빈 객체여야 합니다. 예:{}
.error
객체의 키는 필드의name
값과 일치해야 합니다.
예제:
import React from "react"import { useForm } from "react-hook-form"import { yupResolver } from "@hookform/resolvers/yup"import * as yup from "yup"type Inputs = {name: stringage: string}const schema = yup.object().shape({name: yup.string().required(),age: yup.number().required(),}).required()const App = () => {const { register, handleSubmit } = useForm<Inputs>({resolver: yupResolver(schema), // yup, joi 및 커스텀 리졸버 사용 가능})return (<form onSubmit={handleSubmit((d) => console.log(d))}><input {...register("name")} /><input type="number" {...register("age")} /><input type="submit" /></form>)}
더 많은 정보가 필요하다면 리졸버 문서를 참고하세요.
다음 코드 스니펫을 통해 스키마를 디버깅할 수 있습니다:
resolver: async (data, context, options) => {// 여기서 검증 스키마를 디버깅할 수 있습니다console.log("formData", data)console.log("validation result",await anyResolver(schema)(data, context, options))return anyResolver(schema)(data, context, options)}
useForm
반환값과 useEffect
의존성
향후 주요 릴리스에서 useForm
반환값은 성능 최적화를 위해 메모이제이션되고, formState
의 변경 사항을 반영할 예정입니다.
이로 인해 useForm
의 전체 반환값을 useEffect
의존성 배열에 추가하면 무한 루프가 발생할 수 있습니다.
다음 코드는 이러한 상황을 초래할 가능성이 높습니다:
const methods = useForm()useEffect(() => {methods.reset({ ... })}, [methods])
아래와 같이 관련 메서드만 전달하면 이러한 문제를 피할 수 있습니다:
const methods = useForm()useEffect(() => {methods.reset({ ... })}, [methods.reset])
추천하는 방법은 구조 분해 할당을 통해 메서드를 useEffect
의존성에 전달하는 것입니다.
const { reset } = useForm()useEffect(() => {reset({ ... })}, [reset])
반환 값
아래 목록은 useForm
이 반환하는 프로퍼티들을 참조합니다.
- register
- unregister
- formState
- watch
- handleSubmit
- reset
- resetField
- setError
- clearErrors
- setValue
- setFocus
- getValues
- getFieldState
- trigger
- control
- Form
여러분의 지원에 감사드립니다
React Hook Form이 프로젝트에서 유용하다면, GitHub에서 스타를 눌러 지원해 주세요.