Skip to content

useController

제어 컴포넌트를 위한 리액트 훅

useController:
(props?: UseControllerProps) => { field: object, fieldState: object, formState: object }

이 커스텀 훅은 Controller를 구동합니다. 또한 Controller와 동일한 props와 메서드를 공유합니다. 재사용 가능한 제어 입력 필드를 만드는데 유용합니다.

Props

다음 표는 useController의 인자에 대한 정보를 담고 있습니다.

NameTypeRequiredDescription
nameFieldPath입력 필드의 고유한 이름.
controlControluseForm을 호출하여 제공된 control 객체. FormProvider을 사용할 때에는 선택사항.
defaultValueunknown

중요: useFormdefaultValue 또는 defaultValuesundefined 를 적용할 수 없습니다.

  • 필드 레벨에서 defaultValue를 설정하거나 useFormdefaultValues를 사용해야 합니다. undefined는 사용할 수 없습니다.

  • 폼이 기본값으로 reset을 호출하는 경우, useFormdefaultValues를 제공해야 합니다.

rulesObject

register에서 사용하는 것과 동일한 형식의 유효성 검사 규칙으로, 다음을 포함합니다:

required, min, max, minLength, maxLength, pattern, validate

rules={{ required: true }}
shouldUnregisterboolean = false

입력 필드가 언마운트된 후에는 등록이 해제(unregistered)되며 기본값도 제거됩니다.

참고: 이 prop는 useFieldArray와 함께 사용하지 않아야 합니다. 입력 필드가 언마운트/리마운트되거나 재정렬된 후에 unregister 함수가 호출되기 때문입니다.

disabledboolean = false

disabled prop은 `field` prop에서 반환됩니다. 제어 입력 필드는 비활성화되며, 이 값은 제출(submission) 데이터에서 제외됩니다.

Return

다음 표는 useController가 제공하는 프로퍼티에 대한 정보를 포함하고 있습니다.

stringReact.Ref
Object NameNameTypeDescription
fieldonChange(value: any) => void

입력값을 라이브러리에 전달하는 함수.

  • 이 함수는 입력 필드의 onChange prop에 할당되어야 하며, value는 undefined 가 아니어야 합니다.
  • 이 prop은 formState 를 업데이트 하므로, setValue 또는 필드 업데이트와 관련된 다른 API를 호출하지 않아야 합니다.

fieldonBlur() => void

입력 필드의 onBlur 이벤트를 라이브러리로 전달하는 함수입니다. 이 함수는 입력 필드의 onBlur prop에 할당되어야 합니다.

fieldvalueunknown

제어 컴포넌트의 현재 값.

fielddisabledboolean

입력 필드의 비활성화 상태.

fieldname

등록(registered)된 입력 필드의 이름.

fieldref

hook form을 입력 필드와 연결하는데 사용하는 ref. 이 ref를 컴포넌트 입력 필드의 ref에 할당하면, hook form이 에러가 발생한 입력 필드에 포커스를 맞출 수 있습니다.

fieldStateinvalidboolean

현재 입력 필드의 유효하지 않은 상태.

fieldStateisTouchedboolean

현재 제어 입력 필드의 터치된(touched) 상태.

fieldStateisDirtyboolean

현재 제어 입력 필드의 변경된(dirty) 상태.

fieldStateerrorobject

특정 입력 필드에 대한 에러.

formStateisDirtyboolean

사용자가 입력 중 하나라도 수정한다면 true로 설정됩니다.

  • 중요: 모든 입력의 기본값을 useForm에 제공해야 hook form이 폼이 변경이 되었는지 비교할 수 있는 단일 소스를 가질 수 있습니다.

    const {
    formState: { isDirty, dirtyFields },
    setValue,
    } = useForm({ defaultValues: { test: "" } });
    // isDirty: true
    setValue('test', 'change')
    // isDirty: false 왜냐하면 getValues() === defaultValues 이기 때문
    setValue('test', '')
  • 파일 타입 입력은 파일 선택 취소 및 FileList 객체 관리 때문에 애플리케이션 수준에서 관리되어야 합니다.

  • 사용자 정의 객체, 클래스 또는 파일 객체는 지원하지 않습니다.

formStatedirtyFieldsobject

사용자가 수정한 필드를 포함하는 객체입니다. 라이브러리가 defaultValues와 비교할 수 있도록 useForm을 통해 모든 입력의 defaultValues를 제공해야 합니다.

  • 중요: useForm에서 defaultValues를 제공하여, hook form이 각 필드의 변경 상태를 비교할 수 있는 단일 소스를 가질 수 있도록 해야 합니다.

  • Dirty 필드는 전체 폼이 아닌 개별 필드 수준에서 dirty로 표시되므로, Dirty 필드는 폼이 isDirty 상태임을 나타내지 않습니다. 전체 폼 상태를 확인하려면 isDirty를 사용하세요.

formStatetouchedFieldsobject사용자가 상호작용한 모든 입력을 포함하는 객체입니다.
formStatedefaultValuesobject

useForm의 defaultValues에 설정된 값 또는 reset API를 통해 업데이트된 defaultValues입니다.

formStateisSubmittedboolean폼이 제출된 후 true로 설정됩니다.reset 메서드가 호출될 때까지 true로 유지됩니다.
formStateisSubmitSuccessfulboolean

런타임 에러 없이 폼이 성공적으로 제출되었음을 나타냅니다.

formStateisSubmittingboolean폼이 현재 제출 중이면 true, 그렇지 않으면 false 입니다.
formStateisLoadingboolean

비동기 기본 값을 로드 중인 경우 true입니다.

중요: 이 속성은 비동기 defaultValues에만 적용됩니다.

const {
formState: { isLoading }
} = useForm({
defaultValues: async () => await fetch('/api')
});
formStatesubmitCountnumber폼이 제출된 횟수입니다.
formStateisValidboolean
폼에 에러가 없으면 true로 설정됩니다.

setErrorisValid formState에 영향을 주지 않습니다. isValid는 항상 전체 폼의 유효성 검사 결과를 통해 결정됩니다.

formStateisValidatingboolean유효성 검사 중 true로 설정됩니다.
formStatevalidatingFieldsboolean비동기 유효성 검사가 이뤄지는 필드를 캡쳐합니다.
formStateerrorsobject필드 에러가 포함된 객체입니다. 에러 메세지를 쉽게 가져오기 위해 ErrorMessage도 있습니다.

Examples

import { TextField } from "@material-ui/core";
import { useController, useForm } from "react-hook-form";
function Input({ control, name }) {
const {
field,
fieldState: { invalid, isTouched, isDirty },
formState: { touchedFields, dirtyFields }
} = useController({
name,
control,
rules: { required: true },
});
return (
<TextField
onChange={field.onChange} // hook form에 값 전달
onBlur={field.onBlur} // 입력 필드가 touched/blur 되었을 때 알림
value={field.value} // 입력값
name={field.name} // 입력 필드의 이름을 전달
inputRef={field.ref} // 입력 필드의 ref를 전달하여, 에러가 발생했을 때 입력 필드에 포커스를 맞출 수 있도록 함
/>
);
}
import * as React from "react";
import { useController, useForm } from "react-hook-form";
const Checkboxes = ({ options, control, name }) => {
const { field } = useController({
control,
name
});
const [value, setValue] = React.useState(field.value || []);
return (
<>
{options.map((option, index) => (
<input
onChange={(e) => {
const valueCopy = [...value];
// update checkbox value
valueCopy[index] = e.target.checked ? e.target.value : null;
// send data to react hook form
field.onChange(valueCopy);
// update local state
setValue(valueCopy);
}}
key={option}
checked={value.includes(option)}
type="checkbox"
value={option}
/>
))}
</>
);
};
export default function App() {
const { register, handleSubmit, control } = useForm({
defaultValues: {
controlled: [],
uncontrolled: []
}
});
const onSubmit = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<section>
<h2>uncontrolled</h2>
<input {...register("uncontrolled")} type="checkbox" value="A" />
<input {...register("uncontrolled")} type="checkbox" value="B" />
<input {...register("uncontrolled")} type="checkbox" value="C" />
</section>
<section>
<h2>controlled</h2>
<Checkboxes
options={["a", "b", "c"]}
control={control}
name="controlled"
/>
</section>
<input type="submit" />
</form>
);
}

Tips

  • MUI, AntD, Chakra UI와 같은 외부 제어 컴포넌트를 사용할 때 각 prop의 역할을 이해하는 것이 중요합니다. 이 props는 입력값을 감지하고, 보고하며 설정하는 역할을 합니다.

    • onChange: hook form으로 다시 데이터 전달.

    • onBlur: 입력 필드에서 사용자의 상호작용(focus 및 blur)이 있었음을 보고.

    • value: 입력 필드의 초기 값 및 변경된 값을 설정.

    • ref: 에러 발생 시 해당 입력 필드로 포커스를 이동할 수 있도록 함.

    • name: 입력 필드에 고유한 이름을 부여.

    상태를 직접 관리하면서 useController를 함께 사용하는 것도 괜찮습니다.

    const { field } = useController();
    const [value, setValue] = useState(field.value);
    onChange={(event) => {
    field.onChange(parseInt(event.target.value)) // hook form으로 다시 데이터 전달
    setValue(event.target.value) // UI 상태
    }}
  • 입력을 다시 등록(register)하지 마세요. 이 커스텀 훅은 등록(registration)과정을 처리하도록 설계되었습니다.

    const { field } = useController({ name: 'test' })
    <input {...field} /> // ✅
    <input {...field} {...register('test')} /> // ❌ 등록(registration) 중복
  • 컴포넌트당 하나의 useController를 사용하는 것이 이상적입니다. 만약 여러 개를 사용해야 한다면, name prop을 변경해야 합니다. Controller를 사용하는 것도 고려해보세요.

    const { field: input } = useController({ name: 'test' })
    const { field: checkbox } = useController({ name: 'test1' })
    <input {...input} />
    <input {...checkbox} />

지원해 주셔서 감사합니다

프로젝트에서 React Hook Form이 유용하다고 생각하신다면, 스타를 눌러 지원해 주시길 부탁드립니다.