跳至内容

useController

用于受控组件的 React hook

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

此自定义 Hook 为 Controller提供支持。此外,它与 Controller共享相同的 props 和方法。它对于创建可重用的受控输入很有用。

Props

下表包含有关 useController.

名称类型必需描述
nameFieldPath输入的唯一名称。
controlControlcontrol 通过调用 useForm 提供的对象。在使用 FormProvider 时可选。
defaultValueunknown

重要:不能应用 undefineddefaultValue defaultValuesuseForm

  • 您需要在字段级别设置 defaultValue 或者 useForm defaultValuesundefined 不是有效值。

  • 如果您的表单将使用默认值调用 reset,则需要为 useForm 提供 defaultValues.

rulesObject

register 相同格式的验证规则,包括

required、min、max、minLength、maxLength、pattern、validate

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

输入将在卸载后取消注册,默认值也将被移除。

注意:在与 useFieldArray 一起使用时应避免使用此 prop,因为 unregister 函数在输入卸载/重新安装和重新排序后被调用。

disabledboolean = false

disabled prop 将从 `field` prop 返回。受控输入将被禁用,其值将从提交数据中省略。

返回

下表包含有关 useController 生成的属性的信息。

stringReact.Ref
对象名称名称类型描述
fieldonChange(value: any) => void

将输入的值发送到库的函数。

  • 它应该被分配到输入的 onChange prop,并且值不应该 undefined.
  • 此 prop 更新 formState 并且您应该避免手动调用 setValue 或其他与字段更新相关的 API。

fieldonBlur() => void

将输入的 onBlur 事件发送到库的函数。它应该被分配到输入的 onBlur prop。

fieldvalueunknown

受控组件的当前值。

fielddisabledboolean

输入的禁用状态。

fieldname

正在注册的输入名称。

fieldref

用于将 Hook 表单连接到输入的 ref。分配 ref 到组件的输入 ref,以允许 Hook 表单聚焦错误输入。

fieldStateinvalidboolean

当前输入的无效状态。

fieldStateisTouchedboolean

当前受控输入的已触碰状态。

fieldStateisDirtyboolean

当前受控输入的脏状态。

fieldStateerrorobject

此特定输入的错误。

formStateisDirtyboolean

在用户修改任何输入后设置为 true

  • 重要:确保在 useForm 中提供所有输入的 defaultValues,以便 Hook 表单可以有一个单一的事实来源来比较表单是否已脏。

    const {
    formState: { isDirty, dirtyFields },
    setValue,
    } = useForm({ defaultValues: { test: "" } });
    // isDirty: true
    setValue('test', 'change')
    // isDirty: false because there getValues() === defaultValues
    setValue('test', '')
  • 文件类型输入需要在应用程序级别进行管理,因为可以取消文件选择和 FileList object。

  • 不支持自定义对象、类或文件对象。

formStatedirtyFieldsobject

包含用户修改的字段的对象。确保通过 useForm 提供所有输入的 defaultValues,以便库可以与 defaultValues 进行比较。

  • 重要:确保在 useForm 中提供 defaultValues,以便 Hook 表单可以有一个单一的事实来源来比较每个字段的脏污情况。

  • 脏字段不会被视为 isDirty formState,因为脏字段是在字段级别标记为脏的,而不是整个表单。如果要确定整个表单状态,请改用 isDirty

formStatetouchedFieldsobject包含用户已交互的所有输入的对象。
formStatedefaultValuesobject

useForm 的 defaultValues 或通过 reset API 更新的 defaultValues 中设置的值。

formStateisSubmittedboolean在表单提交后设置为 true。将保持 true 直到 reset 方法被调用。
formStateisSubmitSuccessfulboolean

指示表单已成功提交,没有任何运行时错误。

formStateisSubmittingboolean如果表单当前正在提交,则为 true 否则为 false
formStateisLoadingboolean

如果表单当前正在加载异步默认值,则为 true

重要:此 prop 仅适用于异步 defaultValues

const {
formState: { isLoading }
} = useForm({
defaultValues: async () => await fetch('/api')
});
formStatesubmitCountnumber表单提交的次数。
formStateisValidboolean
如果表单没有任何错误,则设置为 true

setErrorisValid formState 没有影响, isValid 将始终通过整个表单验证结果得出。

formStateisValidatingboolean在验证期间设置为 true
formStatevalidatingFieldsboolean捕获正在进行异步验证的字段。
formStateerrorsobject包含字段错误的对象。还有一个 ErrorMessage 组件可以轻松检索错误消息。

示例

CodeSandbox JS
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} // send value to hook form
onBlur={field.onBlur} // notify when input is touched/blur
value={field.value} // input value
name={field.name} // send down the input name
inputRef={field.ref} // send input ref, so we can focus on input when error appear
/>
);
}
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>
);
}

技巧

  • 在使用外部受控组件(如 MUI、AntD、Chakra UI)时,了解每个 prop 的职责很重要。它的工作是监视输入、报告和设置其值。

    • onChange:将数据发送回 Hook 表单

    • onBlur:报告输入已交互(聚焦和模糊)

    • value:设置输入的初始值和更新后的值

    • ref:允许输入聚焦错误

    • name:为输入提供一个唯一的名称

    可以托管您的状态并与之结合 useController.

    const { field } = useController();
    const [value, setValue] = useState(field.value);
    onChange={(event) => {
    field.onChange(parseInt(event.target.value)) // data send back to hook form
    setValue(event.target.value) // UI state
    }}
  • 不要再次 register 输入。此自定义 Hook 旨在处理注册过程。

    const { field } = useController({ name: 'test' })
    <input {...field} /> // ✅
    <input {...field} {...register('test')} /> // ❌ double up the registration
  • 理想情况下,每个组件只使用一个 useController。如果需要使用多个,请确保重命名 prop。可能需要考虑使用 Controller代替。

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

感谢您的支持

如果您发现 React Hook Form 在您的项目中很有用,请考虑为它点赞和支持。