React Hook Form的性能
性能是创建这个库的主要目标之一。 React Hook Form依赖于非受控组件,这就是为什么register
函数作用在ref
上。 这样将减少由于用户在输入框输入或表单其他值改变而引起的重渲染次数。 因为开销更小,组件会比受控组件更快速地挂载到页面上。 作为参考,我已经完成了一个快速比较测试。
如何创建一个输入组件的辅助错误和消息?
React Hook Form基于非受控组件,它使您能够轻松的构建高可访问性的自定义表单。
import React from "react"; import { useForm } from "react-hook-form"; export default function App() { const { register, handleSubmit, formState: { errors } } = useForm(); const onSubmit = data => console.log(data); return ( <form onSubmit={handleSubmit(onSubmit)}> <label htmlFor="firstName">First name</label> <input id="firstName" aria-invalid={errors.firstName ? "true" : "false"} {...register('firstName', { required: true })} /> {errors.firstName && ( <span role="alert"> This field is required </span> )} <input type="submit" /> </form> ); }
它是否可以与Class类组件一起使用?
不, 不可以直接使用。但是你可以构建一个包裹组件然后在你的类组件中使用。
如何重置表单?
有两种方法清空表单。
- HTMLFormElement.reset()
此方法与单击表单的重置按钮相同,并且只清除
input/select/checkbox
的值。 - React Hook Form API:
reset()
React Hook Form的重置方法将重置所有表单项值,并清空表单内的所有错误。
如何初始化表单值?
由于React Hook Form依赖于非受控组件, 所以可以为单独的表单项指定defaultValue
或defaultChecked
。 但是,更常见的方法是在useForm
传入defaultValue
来初始化表单。
import React from "react"; import { useForm } from "react-hook-form"; export default function App() { const { register, handleSubmit } = useForm({ defaultValues: { firstName: "bill", lastName: "luo", email: "bluebill1049@hotmail.com" } }); const onSubmit = data => console.log(data); return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...register("firstName")} /> <input {...register("lastName")} /> <input {...register("email")} /> <button type="submit">Submit</button> </form> ); }
如何共用ref?
React Hook Form需要ref
来收集输入值,但是,您可能需要将ref
用于其他用途(例如,如果您想要使用它滚动到视图中)。
import React, { useRef } from "react"; import { useForm } from "react-hook-form"; export default function App() { const { register, handleSubmit } = useForm(); const firstNameRef = useRef(null); const onSubmit = data => console.log(data); const { ref, ...rest } = register('firstName'); return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...rest} name="firstName" ref={(e) => { ref(e) firstNameRef.current = e // you can still assign to ref }} /> <button>Submit</button> </form> ); }
import React, { useRef } from "react"; import { useForm } from "react-hook-form"; type Inputs = { firstName: string, lastName: string, }; export default function App() { const { register, handleSubmit } = useForm<Inputs>(); const firstNameRef = useRef<HTMLInputElement | null>(null); const onSubmit = data => console.log(data); const { ref, ...rest } = register('firstName'); return ( <form onSubmit={handleSubmit(onSubmit)}> <input {...rest} name="firstName" ref={(e) => { ref(e) firstNameRef.current = e // you can still assign to ref }} /> <button>Submit</button> </form> ); }
如果无法访问ref怎么办?
您实际上可以在没有ref
的情况下register
输入组件。 事实上,您可以手动调用setValue
,setError
和trigger
。
注意: 由于ref
尚未注册,因此React Hook Form将无法监听输入组件的事件。 这意味着您需要更新值和错误。
import React, { useEffect } from "react"; import { useForm } from "react-hook-form"; export default function App() { const { register, handleSubmit, setValue, setError } = useForm(); const onSubmit = data => console.log(data); useEffect(() => { register("firstName", { required: true }); register("lastName"); }, []); return ( <form onSubmit={handleSubmit(onSubmit)}> <input name="firstName" onChange={e => setValue("firstName", e.target.value)} /> <input name="lastName" onChange={e => { const value = e.target.value; if (value === "test") { setError("lastName", "notMatch") } else { setValue("lastName", e.target.value) } }} /> <button>Submit</button> </form> ); }
浏览器支持?
React Hook Form支持所有主流浏览器。
您可以引入 react-hook-form 的 IE 11 版本以以支持 IE11 。
import { useForm } from 'react-hook-form/dist/index.ie11'; // V6 import { useForm } from 'react-hook-form/dist/react-hook-form.ie11'; // V5' // Resolvers import { yupResolver } from '@hookform/resolvers/dist/ie11/yup';
为什么第一次按键不起作用?
仔细检查是否使用了value
而不是defaultValue
。
React Hook Form是基于非受控输入组件构建的,这意味着您不需要通过statue
和onChange
更改输入值。 因此,您根本不需要value
,事实上,您只需要设置defaultValue
。
因MutationObserver测试失败?
如果您在测试过程中遇到困难,并且问题是由MutationObserver
引起的。 确保安装MutationObserver
并在setup.js file中引用它。
React Hook Form, Formik 还是 Redux Form?
首先,这几个库都在尝试解决同样的问题,尽可能使表单开发变的简单。 然而,三者之间还是有一些根本性区别,react-hook-form是 建立在非受控的输入组件上,并尝试提供给表单最佳的性能和最少重渲染次数。除此之外,react-hook-form是由React Hook构建并作为hook调用, 这意味无须导入组件。 这里有一些的细节差异:
React Hook Form | Formik | Redux Form | |
---|---|---|---|
组件 | 非受控和受控 | 受控 | 受控 |
渲染 | 最少的重渲染 | 在输入组件中输入时,每次本地状态变化都会导致重渲染。 | 在输入组件中输入时,每次状态管理工具(Redux)变化都会导致重渲染。 |
API | Hooks | Component (RenderProps, Form, Field) + Hooks | Component (RenderProps, Form, Field) |
包体积 | 小react-hook-form@3.26.2 | 中formik@2.0.1 | 大redux-form@8.2.6 |
校验 | 自带 Yup, Joi, Superstruct 校验以及自定义构建。 | 使用Yup自定义构建 | 自定义构建或使用插件 |
学习曲线 | 低 | 中 | 中 |
状态 | 成长中的中型社区 | 大社区:社区中非常稳定的表单库 | 大社区:社区中非常稳定的表单库 |
可以用于受控组件吗?
简短的回答:可以
React-hook-form不建议您构建受控表单,但是您仍然可以轻松实现。
可以使用watch
API监听每个输入组件的变化并传递给value
属性。
或者,您可以使用我们的包装器组件Controller,它会为您处理那些自定义注册。
import React from "react"; import { useForm, Controller } from "react-hook-form"; function App() { const { control } = useForm(); return ( <Controller render={({ field }) => <input {...field} />} name="firstName" control={control} defaultValue="" /> ); }
测试 React Hook Form
为什么无法在
React Native (react-native-testing-library)
测试?React Hook Form 并不会在服务端渲染时注册输入组件,这意味着在
react native
中测试会导致window
对象变为undefined
。一个快速的解决方案是将window
对象存储起来以使注册过程可以完成。为什么我会收到
act
警告?React Hook表单中的所有验证方法将被视为异步函数, 因此使用
async
包装act很重要。为什么输入组件更改没有触发事件?
React Hook Form 使用
input
事件处理输入组件变化。如果使用了 react-testing-library 您可以轻松切换到fireEvent.input
。如果你使用了enzyme,就需要手动地设置输入组件对应的 DOM 节点的值,然后触发
input
事件。
我们需要您的支持
如果您发现React Hook Form在您的研究项目中有用,请支持我们和贡献者❤