—————-书接上篇文章————-
验证时机
默认情况下,当单击登录按钮时进行验证。一旦进行了一次验证,之后每次输入文本都会触发验证。
你可以通过useForm
的两个选项mode
和reValidateMode
来控制何时进行验证。还可以手动触发验证。
设置mode
单击登录按钮时进行验证是由mode
选项控制的。默认值是”onSubmit”,但可以更改为”onBlur”、”onChange”、”onTouched”或”all”。虽然从值的名称就可以想象出每个选项的行为,但将mode
的值从”onSubmit”更改为”onChange”会有什么变化,下面我们来看看。
const { register, handleSubmit, formState: { errors } } = useForm<FormData>({
criteriaMode: 'all',
defaultValues: {
email: '243425345@qq.com',
password: '1233444'
},
mode: 'onChange'
});
“onChange”是根据每次输入的文字触发验证,因为它使用了onChange事件。
当使用useState Hook和onChange事件时,每次输入都会导致重新渲染。但是,当将mode
设置为”onChange”时,重新渲染不会在每次输入文字时触发,而是在验证消息的显示/隐藏切换时触发。
如果将mode
更改为”onBlur”,则在将光标从输入框中移出时进行验证。
const { register, handleSubmit, formState: { errors } } = useForm<FormData>({
criteriaMode: 'all',
defaultValues: {
email: '243425345@qq.com',
password: '1233444'
},
mode: 'onBlur'
});
reValidateMode的设置
reValidateMode
用于设置第二次及以后的验证时机。默认情况下,单击登录按钮后进行验证,之后每次输入都会触发验证。您可以使用reValidateMode
来设置第二次验证的时机,默认值是”onChange”,但也可以更改为”onBlur”或”onSubmit”。
const { register, handleSubmit, formState: { errors } } = useForm<FormData>({
criteriaMode: 'all',
defaultValues: {
email: '243425345@qq.com',
password: '1233444'
},
reValidateMode: 'onSubmit'
});
如果将值更改为onSubmit,则仅当您单击登录按钮时才会执行验证。
手动验证
可以使用触发器手动完成验证,触发器是 useForm
返回的对象的属性之一。
const { register, handleSubmit, formState: { errors } ,trigger} = useForm<FormData>({
criteriaMode: 'all',
defaultValues: {
email: '243425345@qq.com',
password: '1233444'
},
});
//略
<div>
<button type="submit">登录</button>
<button type="button" onClick={() => trigger()}>验证</button>
</div>
单击验证按钮执行验证。如果触发器参数中未设置任何内容,将对所有输入项执行验证。如果只想验证密码,请设置触发器(’password’)以仅验证密码。
事实证明,你可以使用 mode
、reValidateMode
和触发器trigger
来控制验证的时间。
“dirty”的设置
为了显示错误消息,我们使用了formState
对象的”errors
“属性,但除了”errors
“属性外,还包含了其他重要的信息可用于表单。”dirty
“的设置可以通过使用”isDirty
“和”dirtyFields
“来进行。
设置”isDirty”
formState
对象有一个属性叫做”isDirty
“。通过使用”isDirty
“属性,你可以检查用户是否已经在表单的任何输入字段中输入了任何字符。默认情况下,”isDirty
“的值为false,但当用户在表单的任何输入字段中输入一个字符时,”isDirty
“的值会从false更改为true。
例如,当页面刚打开时,可以通过将”isDirty
“设置为登录按钮的disable
属性,使按钮无法点击。但是,当用户将焦点放在Email或Password输入字段上并输入字符时,”isDirty
“将从true更改为false,使登录按钮变为可点击状态。
const { register, handleSubmit, formState: { errors ,isDirty} } = useForm<FormData>({
criteriaMode: 'all',
defaultValues: {
email: '',
password: ''
},
});
//略
<div>
<button type="submit" disabled={!isDirty}>登录</button>
</div>
在浏览器中进行操作验证后,正如所描述的,当页面刚打开时,无法立即单击登录按钮。要单击登录按钮,必须在Email或Password字段中输入文本。

配置isDirty
“isDirty”属性用于检查整个表单中是否已经输入内容,而”dirtyFields”属性则允许您分别检查每个输入字段(字段)的”dirty”状态。
要检查Email输入字段是否已经输入内容,可以使用dirtyFields.email
来确认。如果为Email字段设置了默认值,只有在输入与默认值不同的字符时,才能单击按钮。与isDirty
不同,这不会受到Password输入字段的影响。
function App() {
const { register, handleSubmit, formState: { errors ,dirtyFields} } = useForm<FormData>({
criteriaMode: 'all',
defaultValues: {
email: '',
password: ''
},
});
//略
<div>
<button type="submit" disabled={!dirtyFields.email}>登录</button>
</div>
你也可以配置邮箱和密码不为空时才能点击按钮,如下代码:
<div>
<button type="submit" disabled={!dirtyFields.email || !dirtyFields.password}>登录</button>
</div>
其他 formState 属性
除了错误errors
、isDirty
和 dirtyFields
之外,formState
属性还包括以下属性。
-
touchedFields -
isSubmitted -
isSubmitSuccessful -
isSubmitting -
submitCount -
isValid -
isValidating
touchedFields
通过使用touchedFields
,你可以确定是否在每个输入字段上放置光标并移除它。touchedFields
最初是一个空对象,但当你将光标放在Email输入字段上并将其移除时,将添加像下面这样的email
属性。
{
"email": true
}
此外,当你将光标放在Password输入字段上并将其移除时,将添加像下面这样的password
属性。
{
"email": true,
"password"; true
}
isSubmitted
isSubmitted
属性用于在点击登录按钮后将其从false更改为true。
isSubmitting
isSubmitting
属性在执行提交操作期间(通过点击登录按钮)从false更改为true。它可用于防止在提交处理中多次触发按钮。
为了确认submitCount
、isSubmitted
和isSubmitting
属性如何变化,你可以在登录按钮上方添加以下代码。
function App() {
const { register, handleSubmit, formState: {
errors,
dirtyFields,
isSubmitted,
isSubmitting,
submitCount,
}
} = useForm<FormData>({
criteriaMode: 'all',
defaultValues: {
email: '',
password: ''
},
});
const onSubmit = handleSubmit(async (data) => {
await new Promise((resolve) => setTimeout(resolve, 5000));
console.log(data);
});
//省略
<div>
<strong> submitCount : </strong> {JSON.stringify(submitCount)}
</div>
<div>
<strong> isSubmitted : </strong> {JSON.stringify(isSubmitted)}
</div>
<div>
<strong> isSubmitting : </strong> {JSON.stringify(isSubmitting)}
</div>
<div>
<button type="submit" disabled={!dirtyFields.email || !dirtyFields.password}>登录</button>
</div>
在handle函数中添加延迟代码来检查isSubmitting的值是否发生变化。等待 5 秒钟以完成该过程。
输入通过验证的代码后,单击“登录”按钮。
最初,submitCount
的值为0,isSubscribed
和isSubmitting
的值为false。
单击登录按钮时,只有 isSubmiting
的值从 true 更改为 false。5秒后,isSbumitting
的值从true变为false,submitCount
从0变为1,isSubscribed
从false变为true。如果再次点击登录按钮,则submitCount
的值为2。
submitCount
submitCount
属性用于保存已执行的提交操作(通过点击登录按钮)的次数。
isValid
要进行isValid
的操作验证,你可以使用它来确认验证是否失败。默认情况下,isValid
为false,但如果通过了所有验证且没有错误,它将变为true。
以下是如何配置以仅在验证通过时使按钮可点击的设置:
import React from 'react';
import { useForm } from 'react-hook-form';
function App() {
const { register, handleSubmit, formState: { dirtyFields, isValid }, reset } = useForm();
const onSubmit = (data) => {
// 处理表单提交逻辑
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label>Email</label>
<input {...register('email')} />
<label>Password</label>
<input type="password" {...register('password')} />
<button type="submit" disabled={!isValid}>
登录
</button>
</form>
);
}
export default App;
在这个示例中,我们使用isValid
属性来确定验证是否通过。只有当isValid
为true时,登录按钮才会设置为可点击状态。如果有任何验证错误,isValid
将保持为false,按钮将保持禁用状态。这确保了只有在所有验证都通过时,才能提交表单。
reset 重新设置
通过使用reset
函数,你可以重置表单中输入的值以及formState
中包含的属性值。
要添加重置按钮,并在单击按钮时执行reset
函数以确认formState
的属性如何变化,可以使用以下代码进行操作。reset
函数的参数指定了每个字段的值在重置后应设置为什么值。在这里,我们将值设置为与useForm
的defaultValues
相同,但您也可以设置为其他值。重置按钮的type
属性设置为”reset”。
import './App.css'
import {SubmitHandler, useForm} from "react-hook-form";
import {Simulate} from "react-dom/test-utils";
import reset = Simulate.reset;
type FormData = {
email:string;
password:string
}
function App() {
const { register, handleSubmit,reset, formState: {
errors,
isValid,
isDirty,
dirtyFields,
isSubmitted,
isSubmitting,
submitCount,
}
} = useForm<FormData>({
defaultValues: {
email: '',
password: ''
},
});
const onSubmit = handleSubmit( (data) => {
console.log(data);
});
const handleReset = () => {
reset({
email: '',
password: ''
})
}
return (
<>
<h1>登录</h1>
<form onSubmit={onSubmit}>
<div>
<label htmlFor="email">邮箱</label>
<input
id="email"
{...register('email',{required:'邮箱不能为空!'})}
/>
{errors.email?.message && <div style={{color:'red'}}>{errors.email.message}</div>}
{/*{errors.email && <div style={{color:'red'}}>请先填写邮箱</div>}*/}
</div>
<div>
<label htmlFor="password">密码</label>
<input
id="password"
type="password"
{...register('password',{
required: {
value: true,
message: '密码不能为空!'
},
pattern: {
value: /^[A-Za-z]+$/,
message: '请仅输入字母字符',
},
minLength: {
value: 8,
message:'密码长度不能少于8位数'
}
})}
/>
{errors.password?.type === 'required' && (
<div style={{color:'red'}}>{errors.password.message}</div>
)}
{errors.password?.types?.pattern && (
<div style={{color:'red'}}>{errors.password.types.pattern}</div>
)}
{errors.password?.type === 'minLength' && (
<div style={{color:'red'}}>{errors.password.message}</div>
)}
</div>
<div>isValid : {JSON.stringify(isValid)}</div>
<div>isDirty : {JSON.stringify(isDirty)}</div>
<div>
<strong> submitCount : </strong> {JSON.stringify(submitCount)}
</div>
<div>
<strong> isSubmitted : </strong> {JSON.stringify(isSubmitted)}
</div>
<div>
<strong> isSubmitting : </strong> {JSON.stringify(isSubmitting)}
</div>
<div>
<button type="submit" disabled={!dirtyFields.email || !dirtyFields.password}>登录</button>
<button type="reset" onClick={handleReset}>
重置
</button>
</div>
</form>
</>
)
}
export default App
输入时,isValid
和 isDirty
的值变为 true,并将 email 和 password 属性添加到 touchFields
对象中,值变为 true。
当点击Rest按钮时,可以看到isValid
和isDirty
从true变为false,并且touchedFields
的值也被重置。由于没有执行提交,submitCount
和 isSubscribed
值保持不变。

在某些情况下,你可能希望在提交过程成功完成后重置,而不是使用重置按钮,因此将 Reset 函数添加到 onSubmit
函数中。
const onSubmit = handleSubmit((data) => {
console.log(data);
reset({
email: '',
password: '',
});
});
点击登录按钮提交时,就把数据重置为空了。
文档建议在提交后在useEffect
内执行重置。我们来检查一下在useEffect
内部执行reset
函数是否会有什么不同。在useEffect
的依赖项中,我们设置了isSubmitSuccessful
,该值在提交成功时更改。在onSubmit
函数内部,我们对reset
函数进行了注释。
import { useEffect } from 'react'
import './App.css'
import { useForm} from "react-hook-form";
type FormData = {
email:string;
password:string
}
function App() {
const { register, handleSubmit,reset, formState: {
errors,
isValid,
isDirty,
dirtyFields,
isSubmitted,
isSubmitting,
submitCount,
isSubmitSuccessful
}
} = useForm<FormData>({
defaultValues: {
email: '',
password: ''
},
});
useEffect(() => {
reset({
email: '',
password: ''
})
}, [isSubmitSuccessful]);
const onSubmit = handleSubmit( (data) => {
console.log(data);
// reset({
// email: '',
// password: '',
// });
});
const handleReset = () => {
reset({
email: '',
password: ''
})
}
return (
<>
<h1>登录</h1>
<form onSubmit={onSubmit}>
<div>
<label htmlFor="email">邮箱</label>
<input
id="email"
{...register('email',{required:'邮箱不能为空!'})}
/>
{errors.email?.message && <div style={{color:'red'}}>{errors.email.message}</div>}
{/*{errors.email && <div style={{color:'red'}}>请先填写邮箱</div>}*/}
</div>
<div>
<label htmlFor="password">密码</label>
<input
id="password"
type="password"
{...register('password',{
required: {
value: true,
message: '密码不能为空!'
},
pattern: {
value: /^[A-Za-z]+$/,
message: '请仅输入字母字符',
},
minLength: {
value: 8,
message:'密码长度不能少于8位数'
}
})}
/>
{errors.password?.type === 'required' && (
<div style={{color:'red'}}>{errors.password.message}</div>
)}
{errors.password?.types?.pattern && (
<div style={{color:'red'}}>{errors.password.types.pattern}</div>
)}
{errors.password?.type === 'minLength' && (
<div style={{color:'red'}}>{errors.password.message}</div>
)}
</div>
<div>isValid : {JSON.stringify(isValid)}</div>
<div>isDirty : {JSON.stringify(isDirty)}</div>
<div>
<strong> submitCount : </strong> {JSON.stringify(submitCount)}
</div>
<div>
<strong> isSubmitted : </strong> {JSON.stringify(isSubmitted)}
</div>
<div>
<strong> isSubmitting : </strong> {JSON.stringify(isSubmitting)}
</div>
<div>
<button type="submit" disabled={!dirtyFields.email || !dirtyFields.password}>登录</button>
<button type="reset" onClick={handleReset}>
重置
</button>
</div>
</form>
</>
)
}
export default App
在useEffect
内部执行reset
函数时,可以观察到submitCount
和isSubmitted
的值也被重置。尽管屏幕上看不到值的变化,但isSubmitted
的值会变为true,submitCount
的值会变为1。如果不想重置这些值,可以在reset
函数的选项中进行设置。以下示例演示如何不重置submitCount
、isSubmitted
和touchedFields
的值:
useEffect(() => {
reset(
{
email: '',
password: '',
},
{
keepSubmitCount: true,
keepIsSubmitted: true,
keepTouched: true,
}
);
}, [isSubmitSuccessful]);
同样的,我们也可以在onSubmit
函数中设置选项:
const onSubmit = handleSubmit((data) => {
console.log(data);
reset(
{
email: '',
password: '',
},
{
keepSubmitCount: false,
keepIsSubmitted: false,
keepTouched: true,
}
);
});
设置setError
对于前端验证错误,我们已经了解了如何使用React Form Hook来显示它们。但是,对于后端验证错误,可以使用setError
来将从后端接收到的错误添加到React Hook Form的错误中。
以下是一个示例代码,在这个示例中,当点击登录按钮后,onSubmit
函数会抛出一个错误,然后使用setError
函数将错误添加到Email字段的错误中:
import './App.css'
import { useForm} from "react-hook-form";
type FormData = {
email:string;
password:string
}
function App() {
const { register, handleSubmit,setError, formState: {
errors
}
} = useForm<FormData>({
defaultValues: {
email: '',
password: ''
},
});
const onSubmit = handleSubmit((data) => {
console.log(data);
try {
throw new Error('发生错误啦!')
}catch (error: any) {
setError('email',{
type: 'server',
message: error.message
})
console.log(error.message);
}
});
return (
<>
<h1>登录</h1>
<form onSubmit={onSubmit}>
<div>
<label htmlFor="email">邮箱</label>
<input
id="email"
{...register('email',{required:'邮箱不能为空!'})}
/>
{errors.email?.message && <div style={{color:'red'}}>{errors.email.message}</div>}
{/*{errors.email && <div style={{color:'red'}}>请先填写邮箱</div>}*/}
</div>
<div>
<label htmlFor="password">密码</label>
<input
id="password"
type="password"
{...register('password',{
required: {
value: true,
message: '密码不能为空!'
},
pattern: {
value: /^[A-Za-z]+$/,
message: '请仅输入字母字符',
},
minLength: {
value: 8,
message:'密码长度不能少于8位数'
}
})}
/>
{errors.password?.type === 'required' && (
<div style={{color:'red'}}>{errors.password.message}</div>
)}
{errors.password?.types?.pattern && (
<div style={{color:'red'}}>{errors.password.types.pattern}</div>
)}
{errors.password?.type === 'minLength' && (
<div style={{color:'red'}}>{errors.password.message}</div>
)}
</div>
<div>
<button type="submit">登录</button>
</div>
</form>
</>
)
}
export default App
填写表单并单击“登录”按钮时,将显示 setError
中设置的消息。
显示输入的值
要显示输入的值,有多种方法可供选择,但在这里,我们将查看包含在从useForm
返回的对象中的getValues
和watch
。
watch
可以用于获取值,但更重要的是,它允许你监视输入元素的输入,以便立即检测到值的更改。
这两种方法都可以用于获取输入的值,但使用watch
时,每次输入都会触发重新渲染。
使用 getValues 检索
getValues
可以用于获取表单中设置的所有值,也可以用于获取单个值。
要获取Email字段中的值,可以在表单内添加以下代码。但是,请注意,即使你在Email输入字段中输入值,也不会立即显示值。这是因为useForm
的默认mode
是onSubmit
,只有在提交时才会获取值。如果要在输入时立即获取值,可以将mode
更改为onChange
或onBlur
等选项。
function App() {
const {
register,
handleSubmit,
getValues,
formState: { errors },
} = useForm<FormData>({
defaultValues: { email: '', password: '' },
criteriaMode: 'all',
});
//略
<div>{getValues('email')}</div>
如果要显示 getValues
的值,则需要重新绘制它。默认情况下,单击登录按钮时会重绘,因此当您完成输入并单击登录按钮时,输入的值将显示在屏幕上。
通过watch获取
与 getValues
类似,watch
可以检索所有值,但它也可以检索单个值。
在表单中添加以下代码以检索电子邮件中输入的值。还要设置getValues
,其值是通过重新渲染来显示的。
function App() {
const {
register,
handleSubmit,
getValues,
watch,
formState: { errors },
} = useForm<FormData>({
defaultValues: { email: '', password: '' },
criteriaMode: 'all',
});
//略
<div>{watch('email')}</div>
<div>{getValues('email')}</div>
与单独的 getValues
不同,每次您在电子邮件中键入字符时,都会显示您键入的值。由于watch
被重绘,getValues
的值也被更新,并且watch
和getValues
都实时显示输入的值。
使用watch的实例
在文档中已经有关于如何使用watch
的示例,让我们来确认一下如何使用它。在这里,我们将使用watch
来监视showAge
的输入值。watch
的第二个参数可以设置初始值,这里设置为false
。watchShowAge
将保存age
的值,当勾选复选框时,它的值从false
变为true
,只有在选中时才会显示输入元素。
import './App.css'
import { useForm} from "react-hook-form";
type FormData = {
showAge: boolean;
age: string
}
function App() {
const { register, handleSubmit, watch,formState: {
errors
}
} = useForm<FormData>();
const watchShowAge = watch('showAge',false);
const onSubmit = handleSubmit((data) => {
console.log(data);
});
return (
<>
<form onSubmit={onSubmit}>
<div>
<input type="checkbox" {...register('showAge')}/>
</div>
{
watchShowAge && (
<div>
<input type="number" {...register('age',{min:50})}/>
{errors.age && <div style={{color:"red"}}>请输入50或以上</div>}
</div>
)
}
<div>
<button type="submit">发送</button>
</div>
</form>
</>
)
}
export default App

使用watch
监视复选框值,如果选中该复选框,将显示输入元素。
输入值,点击发送的时候,触发onSubmit
函数

如果该篇文章对你有用的话,就请点点关注吧!一起学习前端知识
原文始发于微信公众号(大前端编程教学):在TS环境中React Hook Form表单的创(二)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/224471.html