有许多库可用于创建和管理表单。在React中,表单一直是有点复杂的。表单库的目的是在不影响性能的情况下简化表单管理。
在这篇文章中,我们将看一下React Final Form,一个流行的表单管理库。我们将介绍React Final Form是如何工作的,将它与一些竞争对手进行比较,最后,用一个相关的例子来测试它。让我们开始吧!
什么是React Final Form?
React Final Form 是一个用核心 JavaScript 编写的轻量级表单库,它作为Final Form 的一个封装,是一个表单状态管理库。
React Final Form使用观察者设计模式,其中的组件订阅特定的事件。而不是整个表单重新渲染,只有被订阅的字段才会重新渲染。
让我们来看看React Final Form的一些主要特点。
最小的捆绑尺寸
React Final Form是对Final Form库的简单包装。它没有任何依赖性,而且是用纯JavaScript编写的,这使得它与框架无关。React Final Form的捆绑包大小只有3.2kB,而且是经过压缩的。
简单性
由于其简单的表单状态管理,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.6万颗星,而Formik有27.7万颗星。Formik显然有一个更大的在线社区,然而,这两个库都有大量的线程和论坛,这意味着你应该能够得到社区的支持。
从下面的截图中可以看出,这两个库的更新都很频繁。
React Final Form目前在GitHub上的开放问题比Formik少,但如果该库越来越受欢迎,这种情况在未来可能会改变。
尺寸和依赖性
Formik的bundle大小为13kB,比React Final Form的bundle大小为3.2kB大。
下面,我们可以看到两个库的捆绑构成。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 是父组件,它为我们的表单管理采取了所有的道具,而Field 则包装了HTML元素,以创建一个独立的Final Form组件。由Field 创建的组件有自己的状态,由Form 标签管理。
让我们在React Final Form中编写一个简单的输入表单的代码。我们的代码包含firstName 和lastName 的输入字段。我们还添加了一个submit 按钮。
/* 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中,我们应该始终以较少的重新渲染次数为目标,以避免随着表单大小的增加而出现延迟。
我们使用了一个渲染道具,它使我们能够从Form 组件中访问不同的道具。请看下面我们的例子的最终输出。
现在我们已经看到了React Final Form是如何工作的,让我们用Formik运行同样的例子。
设置Formik
像以前一样,我们将设置一个简单的表单,有一个firstName 的字段,一个lastName 的字段,以及一个提交按钮。让我们把我们的表单称为Client Profile 。
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 标签中放置了一个日志,它将记录渲染的情况。让我们在input 字段中输入Sam 。我们得到下面的输出。
请注意,当我们输入一个输入值时,表单总共重新渲染了九次,而React Final Form的渲染次数只有一次。让我们深入考虑这些例子。
subscription prop
在React Final Form中,Form 组件采取了subscription 道具,它实现了观察者设计模式,并导致更少的渲染。subscription 道具类似于 [useEffect](https://reactjs.org/docs/hooks-effect.html)钩子,因为它观察传递给它的值,并在它们发生变化时重新渲染。
在上面的Formik代码块中,我们没有在prop里面传递值。相反,Form 正在观察{submitting || pristine} 的变化。
验证
React Final Form提供两种类型的验证:表单级验证和字段级验证。通过字段级验证,你可以在Field 被改变时运行验证。在表单级验证中,验证测试是在提交Form 的时候运行的。
Formik有一个类似的验证机制,使用一个 validationSchema.因此,这两个库在这方面是平等的。
总结
React Final Form处理表单的范式与其他库不同。它通过使用观察者设计模式有效地处理了不同库的重新渲染问题。
React Final Form不仅在尺寸上比Formik小,而且速度也更快。因此,如果你的目标是在不影响性能的情况下为你的React应用程序创建大型复杂的表单,React Final Form是最好的选择。
The postReact Final Form:更高性能的表单库首次出现在LogRocket博客上。