Skip to content

useForm

用于表单验证的 React hooks

</> useForm: UseFormProps

useForm 是一个用于轻松管理表单的自定义钩子。它采用一个对象作为可选参数。以下示例演示了其所有属性及其默认值。

¥useForm is a custom hook for managing forms with ease. It takes one object as optional argument. The following example demonstrates all of its properties along with their default values.

通用属性:

¥Generic props:

选项描述
mode提交行为之前验证策略。
reValidateMode提交行为后的验证策略。
defaultValues表单的默认值。
values用于更新表单值的反应值。
错误反应性错误来更新表单错误。
resetOptions更新新表单值时重置表单状态更新的选项。
criteriaMode显示所有验证错误或一次显示一个错误。
shouldFocusError启用或禁用内置焦点管理。
delayError延迟错误立即出现。
shouldUseNativeValidation使用浏览器内置的表单约束 API。
shouldUnregister卸载后启用和禁用输入取消注册。

模式验证属性:

¥Schema validation props:

选项描述
resolver与你首选的架构验证库集成。
context为模式验证提供的上下文对象。

属性

¥Props


模式: onChange | 模糊 | 提交 | 触碰 | all = 'onSubmit' React Native:兼容 Controller


此选项允许你在用户提交表单之前配置验证策略。验证发生在 onSubmit 事件期间,该事件是通过调用 handleSubmit 函数触发的。

¥This option allows you to configure the validation strategy before a user submits the form. The validation occurs during the onSubmit event, which is triggered by invoking the handleSubmit function.

名称类型描述
onSubmitstring验证在 submit 事件上触发,输入附加 onChange 事件监听器以重新验证自身。
onBlurstring验证在 blur 事件上触发。
onChangestring每个输入都会在 changeevent 上触发验证,从而导致多次重新渲染。警告:这通常会对性能产生重大影响。
onTouchedstring验证最初在第一个 blur 事件上触发。之后,每次 change 事件都会触发。

注意:与 Controller 一起使用时,请确保将 onBlurrender 属性连接起来。
allstringblurchange 事件都会触发验证。

reValidateMode:onChange | 模糊 | onSubmit = 'onChange' React Native:自定义注册或使用 Controller


此选项允许你配置在用户提交表单(执行 onSubmit 事件和 handleSubmit 函数)后重新验证有错误的输入时的验证策略。默认情况下,重新验证发生在输入更改事件期间。

¥This option allows you to configure validation strategy when inputs with errors get re-validated after a user submits the form (onSubmit event and handleSubmit function executed). By default, re-validation occurs during the input change event.

默认值:FieldValues | () => Promise<FieldValues>


defaultValues 属性使用默认值填充整个表单。它支持同步和异步分配默认值。虽然你可以使用 defaultValuedefaultChecked (详见 React 官方文档) 设置输入的默认值,但建议对整个表单使用 defaultValues

¥The defaultValues prop populates the entire form with default values. It supports both synchronous and asynchronous assignment of default values. While you can set an input's default value using defaultValue or defaultChecked (as detailed in the official React documentation), it is recommended to use defaultValues for the entire form.

useForm({
defaultValues: {
firstName: '',
lastName: ''
}
})
// set default value async
useForm({
defaultValues: async () => fetch('/api-endpoint');
})
RULES
  • 你应该避免提供 undefined 作为默认值,因为它与受控组件的默认状态冲突。

    ¥You should avoid providing undefined as a default value, as it conflicts with the default state of a controlled component.

  • defaultValues 被缓存。要重置它们,请使用 reset API。

    ¥defaultValues are cached. To reset them, use the reset API.

  • 提交结果中默认包含 defaultValues

    ¥defaultValues will be included in the submission result by default.

  • 建议避免使用包含原型方法的自定义对象,例如 MomentLuxon,而使用 defaultValues

    ¥It's recommended to avoid using custom objects containing prototype methods, such as Moment or Luxon, as defaultValues.

  • 还有其他包含表单数据的选项:

    ¥There are other options for including form data:

    <input {...register("hidden", { value: "data" })} type="hidden" />
    // include data onSubmit
    const onSubmit = (data) => {
    const output = {
    ...data,
    others: "others",
    }
    }

值:FieldValues


values prop 将对更改做出反应并更新表单值,这在你的表单需要通过外部状态或服务器数据更新时很有用。values prop 将覆盖 defaultValues prop,除非 resetOptions: { keepDefaultValues: true } 也设置为 useForm

¥The values prop will react to changes and update the form values, which is useful when your form needs to be updated by external state or server data. The values prop will overwrite the defaultValues prop, unless resetOptions: { keepDefaultValues: true } is also set for 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
})
}

错误:FieldErrors


errors 属性将对更改做出反应并更新服务器错误状态,这在你的表单需要通过外部服务器返回的错误进行更新时非常有用。

¥The errors props will react to changes and update the server errors state, which is useful when your form needs to be updated by external server returned errors.

function App() {
const { errors, data } = useFetch("/api")
useForm({
errors, // will get updated once errors returns
})
}

重置选项:KeepStateOptions


该属性与值更新行为有关。当 valuesdefaultValues 更新时,内部会调用 reset API。指定 valuesdefaultValues 异步更新后所需的行为非常重要。配置选项本身是对 reset 方法选项的引用。

¥This property is related to value update behaviors. When values or defaultValues are updated, the reset API is invoked internally. It's important to specify the desired behavior after values or defaultValues are asynchronously updated. The configuration option itself is a reference to the reset method's options.

// by default asynchronously value or defaultValues update will reset the form values
useForm({ values })
useForm({ defaultValues: async () => await fetch() })
// options to config the behaviour
// eg: I want to keep user interacted/dirty value 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
},
})

上下文:对象


此上下文 object 是可变的,将被注入到 resolver 的第二个参数或 Yup 验证的上下文对象中。

criteriaMode:firstError | 全部


  • When set to firstError (default), only the first error from each field will be gathered.
  • When set to all, all errors from each field will be gathered.

shouldFocusError: boolean = true


当设置为 true(默认)时,并且用户提交验证失败的表单,焦点将设置在第一个有错误的字段上。

¥When set to true (default), and the user submits a form that fails validation, focus is set on the first field with an error.

NOTE
  • 只有带有 ref 的注册字段才有效。自定义注册输入不适用。例如:register('test') // doesn't work

    ¥Only registered fields with a ref will work. Custom registered inputs do not apply. For example: register('test') // doesn't work

  • 焦点顺序基于 register 顺序。

    ¥The focus order is based on the register order.

延迟错误:数字


此配置将向终端用户显示错误状态的时间延迟指定的毫秒数。如果用户纠正了错误输入,则错误会立即消除,并且不会应用延迟。

应该取消注册: boolean = false


默认情况下,删除输入时将保留输入值。但是,你可以在卸载期间设置 shouldUnregistertrueunregister 输入。

¥By default, an input value will be retained when input is removed. However, you can set shouldUnregister to true to unregister input during unmount.

  • 这是一个覆盖子级配置的全局配置。要具有单独的行为,请在组件或钩子级别设置配置,而不是在 useForm 处。

    ¥This is a global configuration that overrides child-level configurations. To have individual behavior, set the configuration at the component or hook level, not at useForm.

  • 默认情况下,shouldUnregister: false 表示未安装的字段不会通过内置验证进行验证。

    ¥By default, shouldUnregister: false means unmounted fields are not validated by built-in validation.

  • 通过在 useForm 级别将 shouldUnregister 设置为 true,defaultValues 将不会与提交结果合并。

    ¥By setting shouldUnregister to true at useForm level, defaultValues will not be merged against submission result.

  • 设置 shouldUnregister: true 使你的表单的行为更接近原生表单。

    ¥Setting shouldUnregister: true makes your form behave more closely to native forms.

    • 表单值存储在输入本身内。

      ¥Form values are stored within the inputs themselves.

    • 卸载输入会删除其值。

      ¥Unmounting an input removes its value.

    • 隐藏输入应使用 hidden 属性来存储隐藏数据。

      ¥Hidden inputs should use the hidden attribute for storing hidden data.

    • 仅注册输入包含为提交数据。

      ¥Only registered inputs are included as submission data.

    • 必须在钩子表单的 useFormuseWatchuseEffect 处通知已卸载的输入,以验证输入是否已从 DOM 中卸载。

      ¥Unmounted inputs must be notified at either useForm or useWatch's useEffect for the hook form to verify that the input is unmounted from the DOM.

      const NotWork = () => {
      const [show, setShow] = React.useState(false)
      // ❌ won't get notified, need to invoke unregister
      return show && <input {...register("test")} />
      }
      const Work = ({ control }) => {
      const { show } = useWatch({ control })
      // ✅ get notified at useEffect
      return show && <input {...register("test1")} />
      }
      const App = () => {
      const [show, setShow] = React.useState(false)
      const { control } = useForm({ shouldUnregister: true })
      return (
      <div>
      // ✅ get notified at useForm's useEffect
      {show && <input {...register("test2")} />}
      <NotWork />
      <Work control={control} />
      </div>
      )
      }

shouldUseNativeValidation: boolean = false


此配置将启用 浏览器原生验证。它还将启用 CSS 选择器 :valid:invalid,使样式输入更容易。即使禁用客户端验证,你仍然可以使用这些选择器。

¥This config will enable browser native validation. It will also enable CSS selectors :valid and:invalid making styling inputs easier. You can still use these selectors even when client-side validation is disabled.

  • 仅适用于 onSubmitonChange 模式,因为 reportValidity 执行将集中错误输入。

    ¥Only works with onSubmit and onChange modes, as the reportValidity execution will focus the error input.

  • 每个注册字段的验证消息都需要是字符串才能本地显示它们。

    ¥Each registered field's validation message is required to be string to display them natively.

  • 此功能仅适用于与实际 DOM 引用连接的 register API 和 useController/Controller

    ¥This feature only works with the register API anduseController/Controller that are connected with actual DOM references.

示例:

¥Examples:


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: "Please enter your first name.",
})} // custom message
/>
<input type="submit" />
</form>
)
}

解析器:Resolver


此功能允许你使用任何外部验证库,例如 YupZodJoiVestAjv 等。目标是确保你可以无缝集成你喜欢的任何验证库。如果你不使用库,你始终可以编写自己的逻辑来验证表单。

¥This function allows you to use any external validation library such as Yup, Zod, Joi, Vest, Ajv and many others. The goal is to make sure you can seamlessly integrate whichever validation library you prefer. If you're not using a library, you can always write your own logic to validate your forms.

npm install @hookform/resolvers
属性

¥Props


名称类型描述
valuesobject该对象包含整个表单值。
contextobject这是你可以提供给 useForm 配置的 context 对象。它是一个可变的 object,可以在每次重新渲染时更改。
options
{
  "criteriaMode": "string",
  "fields": "object",
  "names": "string[]"
}
这是选项对象,包含有关已验证字段、名称和 useForm 中的 criteriaMode 的信息。
RULES
  • 模式验证侧重于字段级错误报告。父级错误检查仅限于直接父级,适用于组复选框等组件。

    ¥Schema validation focuses on field-level error reporting. Parent-level error checking is limited to the direct parent level, which is applicable for components such as group checkboxes.

  • 该函数将被缓存。

    ¥This function will be cached.

  • 在用户交互过程中,一次输入的重新验证只会发生在一个字段中。lib 本身将评估 error 对象以相应地触发重新渲染。

    ¥Re-validation of an input will only occur one field at time during a user’s interaction. The lib itself will evaluate the error object to trigger a re-render accordingly.

  • 解析器不能与内置验证器一起使用(例如:required、min 等)

    ¥A resolver can not be used with the built-in validators (e.g.: required, min, etc.)

  • 构建自定义解析器时:

    ¥When building a custom resolver:

    • 确保返回具有 valueserrors 属性的对象。它们的默认值应该是一个空对象。例如:{}

      ¥Make sure that you return an object with both values and errors properties. Their default values should be an empty object. For example: {}.

    • error 对象的键应与字段的 name 值匹配。

      ¥The keys of the error object should match the name values of your fields.

示例:

¥Examples:


import React from "react"
import { useForm } from "react-hook-form"
import { yupResolver } from "@hookform/resolvers/yup"
import * as yup from "yup"
type Inputs = {
name: string
age: 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 and even your own.
})
return (
<form onSubmit={handleSubmit((d) => console.log(d))}>
<input {...register("name")} />
<input type="number" {...register("age")} />
<input type="submit" />
</form>
)
}
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
const schema = z.object({
name: z.string(),
age: z.number(),
})
type Schema = z.infer<typeof schema>
const App = () => {
const { register, handleSubmit } = useForm<Schema>({
resolver: zodResolver(schema),
})
const onSubmit = (data: Schema) => {
console.log(data)
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("name")} />
<input {...register("age", { valueAsNumber: true })} type="number" />
<input type="submit" />
</form>
)
}
import React from "react";
import { useForm } from "react-hook-form";
import { joiResolver } from "@hookform/resolvers/joi";
import Joi from "joi";
interface IFormInput {
name: string;
age: number;
}
const schema = Joi.object({
name: Joi.string().required(),
age: Joi.number().required()
});
const App = () => {
const { register, handleSubmit, formState: { errors } } = useForm<IFormInput>({
resolver: joiResolver(schema)
});
const onSubmit = (data: IFormInput) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("name"} />
<input type="number" {...register("age"} />
<input type="submit" />
</form>
);
}
import { useForm } from "react-hook-form"
import { ajvResolver } from "@hookform/resolvers/ajv"
// must use `minLength: 1` to implement required field
const schema = {
type: "object",
properties: {
username: {
type: "string",
minLength: 1,
errorMessage: { minLength: "username field is required" },
},
password: {
type: "string",
minLength: 1,
errorMessage: { minLength: "password field is required" },
},
},
required: ["username", "password"],
additionalProperties: false,
}
const App = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
resolver: ajvResolver(schema),
})
return (
<form onSubmit={handleSubmit((data) => console.log(data))}>
<input {...register("username")} />
{errors.username && <p>{errors.username.message}</p>}
<input {...register("password")} />
{errors.password && <p>{errors.password.message}</p>}
<button type="submit">submit</button>
</form>
)
}
import * as React from "react"
import { useForm } from "react-hook-form"
import { vestResolver } from "@hookform/resolvers/vest"
import vest, { test, enforce } from "vest"
const validationSuite = vest.create((data = {}) => {
test("username", "Username is required", () => {
enforce(data.username).isNotEmpty()
})
test("username", "Must be longer than 3 chars", () => {
enforce(data.username).longerThan(3)
})
test("password", "Password is required", () => {
enforce(data.password).isNotEmpty()
})
test("password", "Password must be at least 5 chars", () => {
enforce(data.password).longerThanOrEquals(5)
})
test("password", "Password must contain a digit", () => {
enforce(data.password).matches(/[0-9]/)
})
test("password", "Password must contain a symbol", () => {
enforce(data.password).matches(/[^A-Za-z0-9]/)
})
})
const App = () => {
const { register, handleSubmit } = useForm({
resolver: vestResolver(validationSuite),
})
return (
<form onSubmit={handleSubmit((data) => console.log(data))}>
<input {...register("username")} />
<input {...register("password")} />
<input type="submit" />
</form>
)
}
import * as React from "react"
import { useForm } from "react-hook-form"
import * as Joi from "joi"
interface IFormInputs {
username: string
}
const validationSchema = Joi.object({
username: Joi.string().alphanum().min(3).max(30).required(),
})
const App = () => {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<IFormInputs>({
resolver: async (data) => {
const { error, value: values } = validationSchema.validate(data, {
abortEarly: false,
})
return {
values: error ? {} : values,
errors: error
? error.details.reduce((previous, currentError) => {
return {
...previous,
[currentError.path[0]]: currentError,
}
}, {})
: {},
}
},
})
const onSubmit = (data: IFormInputs) => console.log(data)
return (
<div className="App">
<h1>resolver</h1>
<form onSubmit={handleSubmit(onSubmit)}>
<label>Username</label>
<input {...register("username")} />
{errors.username && <p>errors.username.message</p>}
<input type="submit" />
</form>
</div>
)
}

需要更多?见 解析器文档

¥Need more? See Resolver Documentation

TIP

你可以通过以下代码片段调试你的架构:

¥You can debug your schema via the following code snippet:

resolver: async (data, context, options) => {
// you can debug your validation schema here
console.log("formData", data)
console.log(
"validation result",
await anyResolver(schema)(data, context, options)
)
return anyResolver(schema)(data, context, options)
}

返回

¥Return


以下列表包含对 useForm 返回属性的引用。

¥The following list contains reference to useForm return props.

React Hook Form 中文网 - 粤ICP备13048890号