MaterialUI结合react-hook-form 1 (从一个简单的表单开始)

相关依赖及版本

1
2
3
4
5
6
7
{
"@material-ui.core": "4.11.3",
"react-hook-form": "7.1.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-scripts": "4.0.0"
}

本系列所有文章示例中的依赖均以上述为标准,或者查看对应示例代码CodeSandbox中的版本。

react-hook-form 简单介绍

React Hook Form 是一个高性能、灵活。抑郁校验的表单库。可以用更少的代码获得更好的性能。

详细信息请查看React Hook Form官方文档

需求分析

实现一个带有输入名称、网址来添加书签的表单

编写代码

基础代码

引入需要的模块

1
2
3
import React from "react";
import {Controller, useForm} from "react-hook-forn";
import {Botton, TextEield} from "@material-ui/core";

定义接口

1
2
3
4
interface FormType {
name: string;
url: string;
}

编写form组件

1
2
3
4
5
6
7
8
9
10
11
export default function App() {
return (
<div className="App">
<form>
<TextField label="名称" size="small" variant="outlined" />
<TextField label="网址" size="small" variant="outlined" />
<Button color="primary">提交</Button>
</form>
</div>
)
}

这是一个最基础的表单,不包含事件。

Materal UI 对于表单部分的描述简单,仅有按钮、输入框等组件。从这点上对比Ant Design React的form组件显得过于简单。但同时简单意味着可以根据需求做二次封装,相比Antd的拿来就可以用,Material UI则需要一些额外的东西才可以实现效果。

因此使用React Hook Form显然是一个方便的选择。但它的文档中案例均以原生为基础,没有涉及到UI库的案例,这就导致使用UI库结合React Hook Form上手时往往会出现很多意外的问题。

使用 useFormController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export default function App() {
const {control, handleSubmit} = useForm<FormType>();
const [value, setValue] = React.useState({} as FormType);

const onSubmit = (val: FormType) => {
setValue(val);
}

return (
<div className="App">
<form onSubmit={handleSubmit(onSubmit)}>
{/* ... */}
</form>
</div>
)
}

useForm() 参数请查看:useForm Api,这里我们需要 controlhandleSubmit 这两个部分。

control 用于将组件注册到React Hook Form

handlSubmit 则是表单校验通过时返回数据的事件

使用 Controller 组件控制输入框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
export default function App() {
const { control, handleSubmit } = useForm<formType>();
const [value, setValue] = React.useState({} as formType);

const onSubmit = (val: formType) => {
setValue(val);
};

return (
<div className="App">
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
control={control}
name="name"
render={({ field: { onChange, ref }) => {
return (
<div style={{ display: "block", margin: "10px 0" }}>
<TextField
label="名称"
size="small"
variant="outlined"
onChange={onChange}
inputRef={ref}
/>
</div>
);
}}
/>
<Controller
control={control}
name="url"
render={({field: { onChange, ref }}) => {
return (
<div style={{ display: "block", margin: "10px 0" }}>
<TextField
label="网址"
size="small"
variant="outlined"
onChange={onChange}
inputRef={ref}
/>
</div>
);
}}
/>
<Button type="submit" color="primary" variant="contained">
提交
</Button>
</form>
数据:{JSON.stringify(value)}
</div>
);
}

主要使用的属性:control、name、render具体请看Controller Api

添加校验

现在表单就可以正常使用了,接下来还需要添加校验

Controller 中有一个名为 rules 的属性具体参数参考 useForm()register 属性。

1
2
3
4
<Controller
{...}
rules={{resuired: true}} // 设置必填
/>

现在最基本的使用方式就是这样了,最后是完整的例子:

本文案例(CodeSandbox)