React Hook Form是一个高性能、灵活、易拓展、易于使用的表单校验库,用于React Web&Native的表单验证。
npm i react-hook-form
or
yarn add react-hook-form
这是官方提供的使用方法:
import React from 'react';
import { useForm } from 'react-hook-form';
function App() {
const { register, handleSubmit, errors } = useForm(); // initialise the hook
const onSubmit = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input name="firstname" ref={register} /> {/* register an input */}
<input name="lastname" ref={register({ required: true })} />
{errors.lastname && 'Last name is required.'}
<input name="age" ref={register({ pattern: /\d+/ })} />
{errors.age && 'Please enter number for age.'}
<input type="submit" />
</form>
);
}
{
"version": "2.0",
"actions": [
{
"text": [
{
"markdown": true,
"value": "**ceshi**"
}
],
"type": "section"
},
{
"type": "divider"
},
{
"text": [
{
"markdown": true,
"value": "ceshi1"
}
],
"type": "section"
},
{
"type": "divider"
},
{
"text": [
{
"markdown": false,
"value": "单行文本"
}
],
"type": "section"
},
{
"cate": "text",
"min": 10,
"type": "input",
"required": true,
"label": "标签",
"desc_text": "单行文本",
"max": 100,
"placeholder": "(若外发原因为其他,请填写)",
"name": "other_reason"
},
{
"text": [
{
"markdown": false,
"value": "多行文本"
}
],
"type": "section"
},
{
"cate": "textarea",
"min": 10,
"type": "input",
"required": false,
"label": "标签",
"desc_text": "多行文本",
"max": 100,
"placeholder": "(若外发原因为其他,请填写)",
"name": "other_reason2"
},
{
"type": "divider"
},
{
"text": [
{
"markdown": false,
"value": "单选"
}
],
"type": "section"
},
{
"name": "wf_reason1",
"value": [
"个人或他人共享文件需要留存"
],
"desc_text": "单选",
"type": "select",
"options": [
{
"value": "误操作",
"label": "误操作"
},
{
"value": "其他",
"label": "其他"
}
],
"cate": "radio"
},
{
"text": [
{
"markdown": false,
"value": "下拉"
}
],
"type": "section"
},
{
"cate": "select",
"filterable": true,
"value": [
"个人或他人共享文件需要留存"
],
"desc_text": "下拉",
"type": "select",
"options": [
{
"value": "误操作",
"label": "误操作"
},
{
"value": "其他",
"label": "其他"
}
],
"name": "wf_reason2"
},
{
"text": [
{
"markdown": false,
"value": "多选"
}
],
"type": "section"
},
{
"name": "wf_reason3",
"value": [
"个人或他人共享文件需要留存"
],
"desc_text": "多选",
"type": "select",
"options": [
{
"value": "误操作",
"label": "误操作"
},
{
"value": "其他",
"label": "其他"
}
],
"cate": "checkbox"
},
{
"text": [
{
"markdown": false,
"value": "申请加入群组:919 测试群"
},
{
"value": "申请渠道:群名片"
},
{
"value": "申请加入理由:无"
}
],
"type": "section"
},
{
"type": "submit",
"children": [
{
"text": "拒绝",
"kind": "normal",
"name": "ignore",
"verify": false
},
{
"text": "签收",
"kind": "primary",
"name": "confirm",
"verify": true
}
]
}
]
}
通过type来控制显示的类型,有文本【纯文本,markdown】,下拉【下来,夺权,单选】,输入【input,textarea】,子类用cate来进行控制。
下面是我写的函数,分别对组件进行了封装:
const renderFormItem = useCallback(
(item, index) => {
switch (item.type) {
case 'divider':
return (
<div key={index}>
<div
style={{
border: 'solid 2px #999',
transform: 'scaleY(0.2)',
}}
></div>
<WhiteSpace size="md" />
</div>
);
case 'input':
return (
<Controller
key={index}
name={item.name}
control={control}
defaultValue={item.value}
rules={{
required: item.required
? '【' + item.name + '】输入项不能为空!'
: false,
maxLength: {
value: item.max,
message: '输入不能超过' + item.max + '个字符!',
},
minLength: {
value: item.min,
message: '输入不能小于' + item.min + '个字符!',
},
}}
render={({ field }) => {
return (
<InputComponent
cate={item.cate}
name={item.name}
label={item.label}
desc_text={item.desc_text}
placeholder={item.placeholder}
value={field.value}
max={item.max}
min={item.min}
onChange={(e: any) => {
return field.onChange(e);
}}
/>
);
}}
/>
);
case 'select':
return (
<Controller
key={index}
name={item.name}
control={control}
defaultValue={item.cate === 'radio' ? '' : []}
rules={{
required: item.required
? '【' + item.name + '】选择项不能为空!'
: false,
}}
render={({ field }) => {
return (
<SelectComponent
name={item.name}
cate={item.cate}
options={item.options}
value={field.value}
onChange={(e) => {
return field.onChange(e);
}}
/>
);
}}
/>
);
case 'section':
return (
<TextComponent key={index} text={item.text}>
文本
</TextComponent>
);
case 'submit':
return (
<ButtonComponent
key={index}
childrens={item.children}
type={'submit'}
onClick={(action) => {
handleSubmit(onSubmit(action))();
}}
/>
);
default:
return;
}
},
[control, handleSubmit, onSubmit]
);
onsubmit函数
const onSubmit = useCallback(
(action: string) => {
return (data: any) => {
//可以拿到对应的数据
console.log(action, data);
};
},
[]
);
显示错误提示的函数:
const rederError = (item: any) => {
const err_str = errors[item.name];
if (!err_str) {
return null;
} else {
return <span className={styles['error-info']}>{err_str.message}</span>;
}
};
页面主函数:
<div className={styles['ueba-div']}>
{loading && (
<div className={styles['loading-div']}>
<img
src={'img/loading.gif'}
className={styles['loading-div__img']}
alt=""
/>
</div>
)}
<WingBlank>
<div>
{list.map((item, index) => {
return (
<div key={index}>
{renderUeba(item, index)}
{rederError(item)}
</div>
);
})}
</div>
</WingBlank>
</div>
参考文章:
https://react-hook-form.com/api/usecontroller/controller/
上述只是个用法代码,下次准备写一版封装好的form组件