有许多库可用于创建和管理表单。在React中,表单一直是有点复杂的。表单库的目的是在不影响性能的情况下简化表单管理。
在本文中,我们将介绍 React Final Form,这是一个流行的表单管理库。我们将介绍 React Final Form 的工作原理,将其与一些竞争对手进行比较,最后用相关示例对其进行测试。让我们开始吧!
什么是React Final Form?
React Final Form是一个用JavaScript编写的轻量级表单库,它作为Final Form的包装,是一个表单状态管理库。
React Final Form使用观察者设计模式,其中的组件订阅了特定的事件。而不是整个表单重新渲染,只有被订阅的字段才会重新渲染。
让我们来看看 React Final Form 的一些主要特性。
最小bundle大小
React Final Form是Final Form库的一个简单包装。它没有任何依赖性,而且是用纯JavaScript编写的,这使得它与框架无关。React Final Form的捆绑包大小只有3.2kB,已被压缩和gzipped。
简洁性
由于其简单的表单状态管理,React Final Form强调为需要的功能编写代码,而不是为简单的表单编写不必要的代码。React Final Form的设计是高度模块化的,使其成为许多使用案例的完美选择。
高性能
虽然在小表单中重新渲染不是什么大问题,但随着表单大小的增加,我们看到每次重新渲染的性能明显滞后。由于其基于订阅的模式,React Final Form只重新渲染所需的字段,从而避免了延迟。
现在我们已经了解了React Final Form的基本知识,让我们来看看Formik,一个类似的库,看看两者的比较。
与 Formik 的比较
Formik是一个库,它在编写React代码的三个方面为开发者提供帮助:从表单状态中获取数值,验证和错误信息,以及表单提交。
人气和社区
让我们看看这两个库在npm上的趋势,以衡量受欢迎程度和社区规模。我们看到,在过去的六个月里,Formik获得了比React Final Form更多的每周下载量。
在 GitHub 上,React Final Form 有 6.6K 颗星,而 Formik 有 27.7K 颗星。 Formik 显然有一个更大的在线社区,但是,这两个库都有很多主题和论坛,这意味着您应该能够获得社区支持。
如下图所示,这两个库都经常更新:
React Final Form 目前在 GitHub 上的未解决问题比 Formik 少,但如果该库越来越受欢迎,这在未来可能会改变。
大小和依赖关系
Formik的包大小是13kB,比React Final Form的3.2 kB大。
下面,我们可以看到这两个库的包组合。React Final Form有更少的依赖,减少了库在更新时崩溃的机会。
设置 React Final Form
让我们通过启动自己的项目来测试React Final Form的功能。运行以下命令,建立React项目并安装React Final Form库:
npm install --save final-form react-final-form
安装库后,从库中导入主要组件,如下所示:
import { Form, Field } from 'react-final-form'
请注意,在上面的代码片段中,我们导入了两个组件,Form
和 Field
。 Form
是父组件,它接受我们表单管理的所有 props,Field
包装 HTML 元素以创建一个独立的 Final Form 组件。 Field
创建的组件有自己的状态,由 Form
标签管理。
让我们在React Final form中为一个简单的输入表单编写代码。我们的代码包含 firstName
和 lastName
的输入字段。我们还添加了一个提交按钮:
/* eslint-disable jsx-a11y/accessible-emoji */
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 - Simple Example</h1>
<Form
onSubmit={onSubmit}
initialValues={{ firstname: '', lastname :''}}
render={({ handleSubmit, form, submitting, pristine, values }) => (
<form onSubmit={handleSubmit}>
<div>
<label>First Name</label>
<Field
name="firstName"
component="input"
type="text"
placeholder="First Name"
/>
</div>
<div>
<label>Last Name</label>
<Field
name="lastName"
component="input"
type="text"
placeholder="Last Name"
/>
</div>
<div className="buttons">
<button type="submit" disabled={submitting || pristine}>
Submit
</button>
<button
type="button"
onClick={form.reset}
disabled={submitting || pristine}
>
Reset
</button>
</div>
</form>
)}
/>
</Styles>
)
render(<App />, document.getElementById('root'))
启动服务器将得到以下输出。
我们调用了两个日志,一个来自 Form
,一个来自 Field
。让我们尝试在 FirstName
中输入 sam
,看看会发生什么!
请注意,Form
只渲染了一次。 Field
组件显示了独立的行为,因为它渲染的次数与输入的字符数相同。在 React 中,我们应该始终针对较少数量的重新渲染,以避免随着表单大小的增长而出现延迟。
我们使用了一个render prop,它让我们可以从 Form
组件访问不同的道具。请参阅下面我们示例的最终输出:
现在我们已经了解了 React Final Form 的工作原理,让我们使用 Formik 运行相同的示例。
设置 Formik
和前面一样,我们将设置一个简单的表单,其中包含一个 firstName
字段、一个 lastName
字段和一个提交按钮。让我们调用我们的表单客户资料:
import React from "react";
import ReactDOM from "react-dom";
import { Formik, Form, Field } from "formik";
// Messages
export default function App() {
return (
<Formik
initialValues={{
firstname: "",
lastname: "",
}}
onSubmit={(values, { setSubmitting }) => {
setTimeout(() => {
console.log(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 400);
}}
>
{({ errors, touched, isValidating }) => (
<div className="container">
<div>
<h3>Client Profile</h3>
</div>
<div>
<Form>
{console.log(“Render”)}
<div>
<Field
type="text"
placeholder="First Name"
name="firstname"
/>
</div>
<div>
<Field
type="text"
placeholder="lastname"
name="name"
/>
</div>
<button type="submit">Submit</button>
</Form>
</div>
</div>
)}
</Formik>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
在第一次渲染时,我们的表单如下图所示:
我们在 Form
标签内放置了一个日志,它将记录渲染的情况。让我们在输入栏中输入 Sam
。我们得到以下输出:
请注意,当我们输入一个输入值时,表单总共重新渲染了9次,而React Final Form的渲染次数只有一次。让我们深入考虑这些例子。
subscription prop
在 React Final Form 中,Form
组件采用 subscription
prop,它实现了观察者设计模式并导致更少的渲染。subscription
prop 类似于 useEffect
Hook,因为它监视传递给它的值,并在更改时重新渲染。
在上面的 Formik 代码块中,我们没有在 prop 中传递值。相反,Form
正在观看 {submitting || pristine}
的变化。
Validation
React Final Form 提供两种类型的验证:表单级验证和字段级验证。使用字段级验证,您可以在更改字段时运行验证。在表单级验证中,在提交表单时运行验证测试。
Formik 有一个类似的验证机制,使用 validationSchema
进行验证。因此,这两个库在这方面是平等的。
总结
React Final Form处理表单的范式与其他库不同。它通过使用观察者设计模式有效地处理了不同库的重新渲染问题。
React Final Form 不仅比 Formik 更小,而且速度更快。因此,如果您的目标是在不影响性能的情况下为 React 应用程序创建大型复杂的表单,React Final Form 是最佳选择。