设计思路
- 状态管理:使用
useState
来管理表单的值、错误信息以及验证状态(是否正在验证)。
- 异步验证:利用
async/await
处理异步验证逻辑,如调用 API 进行远程验证。
- 错误提示:将错误信息与对应的表单字段关联,在验证失败时显示。
- 集成现有表单组件:通过返回函数和状态,让表单组件可以方便地调用验证逻辑和获取验证结果。
实现步骤
- 创建自定义 Hook:
import { useState, useEffect } from 'react';
const useFormValidation = () => {
const [formValues, setFormValues] = useState({});
const [errors, setErrors] = useState({});
const [isValidating, setIsValidating] = useState(false);
// 处理表单值的变化
const handleChange = (e) => {
const { name, value } = e.target;
setFormValues({
...formValues,
[name]: value
});
};
// 异步验证函数
const asyncValidate = async (field, value) => {
// 模拟异步验证,实际应用中可以调用 API
return new Promise((resolve) => {
setTimeout(() => {
if (field === 'email' &&!value.match(/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/)) {
resolve('Invalid email');
} else {
resolve(null);
}
}, 1000);
});
};
// 进行整体验证
const validate = async () => {
setIsValidating(true);
const newErrors = {};
for (const [field, value] of Object.entries(formValues)) {
const error = await asyncValidate(field, value);
if (error) {
newErrors[field] = error;
}
}
setErrors(newErrors);
setIsValidating(false);
};
return {
formValues,
errors,
isValidating,
handleChange,
validate
};
};
- 在表单组件中使用:
import React from'react';
import useFormValidation from './useFormValidation';
const FormComponent = () => {
const { formValues, errors, isValidating, handleChange, validate } = useFormValidation();
const handleSubmit = async (e) => {
e.preventDefault();
await validate();
if (Object.keys(errors).length === 0) {
// 提交表单逻辑
console.log('Form submitted successfully', formValues);
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
name="email"
value={formValues.email || ''}
onChange={handleChange}
placeholder="Email"
/>
{errors.email && <span style={{ color:'red' }}>{errors.email}</span>}
<button type="submit" disabled={isValidating}>
{isValidating? 'Validating...' : 'Submit'}
</button>
</form>
);
};
export default FormComponent;
确保可复用性和稳定性
- 可复用性:
- 参数化验证逻辑:将异步验证函数作为参数传入 Hook,这样不同表单可以有不同的验证逻辑。
- 通用接口设计:返回通用的函数(如
handleChange
、validate
)和状态(如 formValues
、errors
),便于不同表单组件集成。
- 稳定性:
- 错误处理:在异步验证函数中添加适当的错误处理,确保即使验证过程出错,Hook 不会崩溃。
- 测试:编写单元测试和集成测试,确保 Hook 在各种输入情况下都能正常工作,验证逻辑正确。例如使用 Jest 和 React Testing Library 进行测试。