没有人喜欢创建和重新创建带有验证的复杂表单,包括React开发人员。
在React中构建表单时,必须使用一个表单库,该库提供了许多方便的工具,而且不需要太多代码。
基于实用和简单这两个标准,应用程序最理想的React表单库是 React-hook-form
。
让我们看看如何在你自己的项目中使用 React-hook-form
来为你的React应用程序构建丰富的、有特色的表单。
安装
让我们来讨论一个典型的用例:一个用户注册到我们的应用程序。
对于我们的注册表单,我们将为任何新用户的用户名、密码和电子邮件提供三个输入:
import React from "react"; const styles = { container: { width: "80%", margin: "0 auto", }, input: { width: "100%", }, }; export default function Signup() { return ( <div style={styles.container}> <h4>Sign up</h4> <form> <input placeholder="Username" style={styles.input} /> <input placeholder="Email" style={styles.input} /> <input placeholder="Password" style={styles.input} /> <button type="submit">Submit</button> </form> </div> ); }
一旦React项目启动并运行,我们将从安装 React-hook-form
库开始:
npm i react-hook-form
使用 useForm hook
要使用 react-hook-form
,我们只需要调用 useForm
钩子即可。
当我们这样做的时候,我们将得到一个对象,我们将从中解构register属性。
register是一个函数,我们需要将它连接到每个输入,作为 ref
。
function App() { const { register } = useForm(); return ( <div style={styles.container}> <h4>Signup</h4> <form> <input ref={register} placeholder="Username" style={styles.input} /> <input ref={register} placeholder="Email" style={styles.input} /> <input ref={register} placeholder="Password" style={styles.input} /> <button type="submit">Submit</button> </form> </div> ); }
register函数将接受用户在每个输入中输入的值,以验证它。Register还将把每个值传递给一个函数,该函数将在提交表单时被调用,下面我们将讨论这个问题。
为了让register正常工作,我们需要为每个输入提供一个适当的name属性。例如,对于用户名输入,它的名称为“username”。
这样做的原因是,当我们提交表单时,我们将获得单个对象上的所有输入值。每个对象的属性都将根据我们指定的输入名称属性进行命名。代码如下:
function App() { const { register } = useForm(); return ( <div style={styles.container}> <h4>My Form</h4> <form> <input name="username" ref={register} placeholder="Username" style={styles.input} /> <input name="email" ref={register} placeholder="Email" style={styles.input} /> <input name="password" ref={register} placeholder="Password" style={styles.input} /> <button type="submit">Submit</button> </form> </div> ); }
使用 handleSubmit 提交表单
为了处理提交表单和接收输入数据,我们将在表单元素中添加一个onSubmit,并将其连接到同名的本地函数:
function App() { const { register } = useForm(); function onSubmit() {} return ( <div style={styles.container}> <h4>My Form</h4> <form onSubmit={onSubmit}> <input name="username" ref={register} placeholder="Username" style={styles.input} /> <input name="email" ref={register} placeholder="Email" style={styles.input} /> <input name="password" ref={register} placeholder="Password" style={styles.input} /> <button type="submit">Submit</button> </form> </div> ); }
从useForm
中,我们将获取一个名为handlessubmit
的函数,并将其作为一个高阶函数包装在onSubmit
周围。
handlessubmit
函数将负责收集输入到每个输入中的所有数据,我们将在onSubmit
中接收到一个名为data
的对象。
现在,如果我们使用 console.log(data)
,我们就可以看到我们在同一个属性的每个输入中输入了什么:
function App() { const { register, handleSubmit } = useForm(); function onSubmit(data) { console.log(data); // { username: 'test', email: 'test', password: 'test' } } return ( <div style={styles.container}> <h4>Signup</h4> <form onSubmit={handleSubmit(onSubmit)}> <input name="username" ref={register} placeholder="Username" style={styles.input} /> <input name="email" ref={register} placeholder="Email" style={styles.input} /> <input name="password" ref={register} placeholder="Password" style={styles.input} /> <button type="submit">Submit</button> </form> </div> ); }
表单验证
验证表单并为每个输入值添加约束非常简单——我们只需要将信息传递给register函数。
register接受一个对象,该对象包含许多属性,这些属性告诉register如何验证给定的输入。
第一个属性是必需的。默认情况下,它被设置为false,但我们可以将其设置为true,以确保没有填写表单时不提交。
我们希望用户名值是必需的,并且希望用户的用户名大于6个字符但小于24个字符。
为了应用这个验证,我们可以将minLength的约束设置为6,但是maxLength应该是20:
<input name="username" ref={register({ required: true, minLength: 6, maxLength: 20, })} style={styles.input} placeholder="Username" />
如果我们为这个输入使用数字(假设这个输入是关于人的年龄的),我们将使用属性min和max而不是minLength和maxLength。
正则表达式
接下来,如果愿意,我们可以提供一个 regex 正则表达式
模式。
如果我们希望用户名只包含大写和小写字符,我们可以使用下面的正则表达式,它允许自定义验证:
<input name="username" ref={register({ required: true, minLength: 6, maxLength: 20, pattern: /^[A-Za-z]+$/i, })} style={styles.input} placeholder="Username" />
validate
最后是validate
,这是一个自定义函数,它允许我们访问输入的值。validate
允许我们提供自己的逻辑来确定它是否有效(通过返回布尔值true或false)。
对于这里的电子邮件,我们也希望它是必需的,并且是有效的电子邮件。为了验证这一点,我们可以将输入传递给来自名为 isEmail的库
验证器的函数。
如果输入的是电子邮件,则返回true。否则,错误的:
<input name="email" ref={register({ required: true, validate: (input) => isEmail(input), // returns true if valid })} style={styles.input} placeholder="Email" />
对于password的register函数,我们将required设置为true, minlength设置为6,不设置maxLength:
<input name="password" ref={register({ required: true, minLength: 6 })} style={styles.input} placeholder="Password" />
错误提示
现在,如果表单中的输入无效,我们不会告诉用户有任何错误。我们需要给他们反馈来修复他们提供的值。
当其中一个输入无效时,表单数据不会被提交(不会调用onSubmit)。此外,带有错误的第一个输入将自动聚焦,它不会向用户提供关于所发生事情的任何详细反馈。
我们可以从 useForm
中获取一个 errors对象
,而不仅仅是不提交表单。
就像我们在 onSubmit
中获得的数据函数一样,errors
包含对应于每个输入名称的属性,如果它有错误的话。
对于我们的示例,我们可以为每个输入添加一个条件,并说如果有错误,我们将把borderColor
设置为红色。
function App() { const { register, handleSubmit, errors } = useForm(); function onSubmit(data) { console.log(data); } return ( <div style={styles.container}> <h4>My Form</h4> <form onSubmit={handleSubmit(onSubmit)}> <input name="username" ref={register({ required: true, minLength: 6, maxLength: 20, pattern: /^[A-Za-z]+$/i, })} style={{ ...styles.input, borderColor: errors.username && "red" }} placeholder="Username" /> <input name="email" ref={register({ required: true, validate: (input) => isEmail(input), })} style={{ ...styles.input, borderColor: errors.email && "red" }} placeholder="Email" /> <input name="password" ref={register({ required: true, minLength: 6, })} style={{ ...styles.input, borderColor: errors.password && "red" }} placeholder="Password" /> <button type="submit" disabled={formState.isSubmitting}> Submit </button> </form> </div> ); }
验证模式
您会注意到,默认情况下,errors对象
只有在提交表单时才会更新。默认的验证只在提交表单时执行。
我们可以通过给useForm
传递一个对象来改变这一点,我们可以在需要执行验证时设置模式:onBlur、onChange或onSubmit
。
每当用户’失去焦点’或点击远离输入,onBlur
将使验证运行。onChange
是用户输入时验证,onSubmit
是表单提交时验证。
对于我们的表单,让我们选择 onBlur
:
const { register, handleSubmit, errors } = useForm({ mode: "onBlur", });
请注意,还有其他方法可以手动设置和清除错误(setError
和clearError
)。例如,在某些情况下,您希望它在onSubmit中创建一个不同的错误或清除一个错误,就可以使用这些方法。
如何禁用表单的formState
我们可以从useForm
钩子中得到的最后一个值是formState
。
它为我们提供了重要的信息,比如何时输入了某些内容,以及何时提交了表单。
因此,如果你想禁用表单的按钮,以确保表单没有提交过多次,我们可以将禁用设置为formstate.issubmitted
。
提交表单时,它会被禁用直到验证完成运行onSubmit
函数。
总结
我希望本文向您展示了如何在React应用程序中更容易地创建功能性表单。
还有很多与react-hook形式相关的特性我没有在这里介绍。点击这里,官方文档应该涵盖你能想到的任何用例。