表单无处不在,它是每个网站的必备部分。在用React构建web应用时,处理表单是不可避免的。
你可以选择自己的方式来处理,或者选择社区中现成的库。然而,当你选择一个第三方库时,你会立即面临一个问题:有太多的库可供选择。
选择一个库是一件棘手的事情,随意选择一个GitHub上星标多的库并不总是明智的。你肯定需要阅读文档、代码示例,并多次尝试,才能确定这是你想要用于自己项目的库。
对于处理表单,我们有以下选择:
库名称 | GitHub星标 | 下载次数 | 体积 |
---|---|---|---|
formik | 23.4K | 868k/周 | 7.22 kB |
final-form | 2.5K | 222k/周 | 5.1 kB |
react-Form | 1.9K | 12k/周 | 4.3 kB |
react-hook-form | 12.5K | 270k/周 | 8.67 kB |
redux-form | 12.3K | 389k/周 | 26.4 kB |
在这里中,我们将比较下载次数最多的三个库:formik、final-form和react-hook-form。
对于redux-form,我们可以忽略它,毕竟已经是2020年了,没有人会再把每个输入的keystore存储在Redux中,这极其影响性能。而且该库的作者也建议大家转向使用final-form。
使用方式比较
Formik
在GitHub星标数量、下载次数方面,formik是使用人数最多的库,星标最多,下载次数也最多。
老实说,我不喜欢formik的口号“无需含泪构建表单”,因为在React中构建表单和验证从未过于复杂。
使用formik,你需要在组件的render部分直接渲染Formik的Form组件:
import React from "react";
import { Formik } from "formik";
const Basic = () => (
<div>
<h1>在你的应用任何地方!h1>
<Formik
initialValues={{ email: "", password: "" }}
validate={(values) => {
const errors = {};
if (!values.email) {
errors.email = "必填";
} else if (
!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,}$/i.test(values.email)
) {
errors.email = "无效的电子邮件地址";
}
return errors;
}}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
/* 和其他好东西 */
}) => (
<form onSubmit={handleSubmit}>
<input
type="email"
name="email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
/>
{errors.email && touched.email && errors.email}
<input
type="password"
name="password"
onChange={handleChange}
onBlur={handleBlur}
value={values.password}
/>
{errors.password && touched.password && errors.password}
<button type="submit" disabled={isSubmitting}>
提交
button>
form>
)}
Formik>
div>
);
export default Basic;
上述代码相当长,并且有一些缺点:
- 你必须在组件内直接渲染Formik组件,这使得你的渲染部分相对混乱。
- 你必须手动将handleChange、handleBlur等函数映射到输入元素上,这项工作相当耗时。不过,你可以使用formik的Field或ErrorMessage组件来节省时间。
- Formik没有内置验证,你需要自己编写函数来验证表单值,或者使用像yup这样的库来支持验证。
- Formik不支持完整的hook,尽管你可以使用useFormik hook,但使用这个hook时,Field、ErrorMessage、FieldArray等组件将无法工作。
Final-Form
final-form由redux-form的作者编写,因此相当有名。
创建一个final-form表单如下:
import React from "react";
import { render } from "react-dom";
import Styles from "./Styles";
import { Form, Field } from "react-final-form";
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const onSubmit = async (values) => {
await sleep(300);
window.alert(JSON.stringify(values, 0, 2));
};
const App = () => (
<Styles>
<h1>React Final Form示例h1>
<h2>密码/确认验证h2>
<a
href="https://final-form.org/react"
target="_blank"
rel="noopener noreferrer"
>
阅读文档
a>
<Form
onSubmit={onSubmit}
validate={(values) => {
const errors = {};
if (!values.username) {
errors.username = "必填";
}
if (!values.password) {
errors.password = "必填";
}
if (!values.confirm) {
errors.confirm = "必填";
} else if (values.confirm !== values.password) {
errors.confirm = "必须匹配";
}
return errors;
}}
render={({ handleSubmit, form, submitting, pristine, values }) => (
<form onSubmit={handleSubmit}>
<Field name="username">
{({ input, meta }) => (
<div>
<label>用户名label>
<input {...input} type="text" placeholder="用户名" />
{meta.error && meta.touched && <span>{meta.error}span>}
div>
)}
Field>
<Field name="password">
{({ input, meta }) => (
<div>
<label>密码label>
<input {...input} type="password" placeholder="密码" />
{meta.error && meta.touched && <span>{meta.error}span>}
div>
)}
Field>
<Field name="confirm">
{({ input, meta }) => (
<div>
<label>确认label>
<input {...input} type="password" placeholder="确认" />
{meta.error && meta.touched && <span>{meta.error}span>}
div>
)}
Field>
<div className="buttons">
<button type="submit" disabled={submitting}>
提交
button>
<button
type="button"
onClick={form.reset}
disabled={submitting || pristine}
>
重置
button>
div>
<pre>{JSON.stringify(values, 0, 2)}pre>
form>
)}
/>
Styles>
);
render(<App />, document.getElementById("root"));
在我看来,使用final-form的方式与formik类似,但在渲染Form组件后,你必须使用Field组件来传递final-form的props到你的输入元素。
因此,将final-form与react-select等其他React组件集成可能会有些困难。
此外,final-form没有内置验证,你必须自己编写函数来验证表单数据。
Final-form也不支持joi或yup,你必须自己找到方法让final-form能够使用yup,如下所示:链接
React-Hook-Form
第一次看到是在reddit上(www.reddit.com/r/reactjs)上…
使用react-hook-form的方式如下:
import React from "react";
import { useForm } from "react-hook-form";
export default function App() {
const { register, handleSubmit, watch, errors } = useForm();
const onSubmit = data => console.log(data);
console.log(watch("example"));
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input name="example" defaultValue="test" ref={register} />
<input name="exampleRequired" ref={register({ required: true })} />
{errors.exampleRequired && <span>这个字段是必填的span>}
<input type="submit" />
form>
);
}
在这三个库中,我认为react-hook-form是最容易使用的。你只需要使用useForm来创建表单,同时使用register来将输入注册到react-hook-form。
当你将react-hook-form与react-select等其他表单输入库一起使用时,也非常简单,你可以使用setValue函数将该组件的值传递给react-hook-form。
React-hook-form还提供了一些内置函数来验证表单内容:
import React from "react";
import { useForm } from "react-hook-form";
export default function App() {
const { register, handleSubmit } = useForm();
const onSubmit= data => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
name="firstName"
ref={register({ required: true, maxLength: 20 })}
/>
<input
name="lastName"
ref={register({ pattern: /^[A-Za-z]+$/i })}
/>
<input
name="age"
type="number"
ref={register({ min: 18, max: 99 })}
/>
<input type="submit" />
form>
);
}
同时,你也可以使用像yup这样的库来验证表单内容。
react-hook-form 基于非受控组件,这意味着你不需要通过状态和 onChange 事件来更新输入值。相反,你只需要设置 defaultValue。
根据react-hook-form的官网,由于它限制了不必要的组件重新渲染次数,并且具有最低的挂载时间,因此它具有最佳的性能。
另外它体积小(压缩后仅8.6 kB),而且没有外部依赖,使得应用的加载速度更快,同时也减少了项目的复杂性。
结论
react-hook-form是目前最容易使用的库,同时它的文档也非常好。在我看来,react-hook-form唯一的限制是它只能与函数组件一起使用。因此,如果你的项目仍然在使用旧版本的React,那么你就无法使用它。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=20843,转载请注明出处。
评论0