使用Formik轻松开发更高质量的React表单(一)入门

前言



发现Formik是在我学习redux-form过程中从国外一篇博客上偶然发现的,看到作者的高度肯定后我立即转到github上,正如许多朋友所注意的,我发现其星数达8282,这个数字在github虽然不算很高,但是在探讨基于React技术开发跨平台表单这个主题的开源库角度来看,这个数字已经相当不错了。不自觉地,我对比了redux-form与Formik的几个数据,如下:

开源库的时间 星数
redux-form 3年以前 10210
Formik 1年前 8282

几个不太肯定的结论(欢迎有兴趣的朋友一起讨论):
1,redux-form是目前基于React+Redux开发构建表单子项目时主要开源对象选择;
2,redux-form很可能是目前大多数React程序员心目中认为是高效率的选择方案;
3,我的预言是:在github上Formik在未来一年后星数很有可能会超过redux-form项目。

我作出上述猜测主要理由是,经过这段时间我redux-form学习,我发现要深度掌握redux-form实践应用并灵活地处理各种有关问题,需要花费相当的代价。尤其说明问题的是,在表单体积膨胀和数量急剧增加的情况下,系统的性能有可能受到严重的影响。现在我有了react-redux基础,并理解了redux-form应用原理后,感觉使用Formik开发React表单一下变得异常轻松愉快!

为了节约时间,本系列的几篇我会首先使用英语方式,再在后面的时间里逐篇翻译成中文。

Why not Redux-Form?

By now, you might be thinking, "Why didn‘t you just use Redux-Form?" Good question.


  1. According to our prophet Dan Abramov, form state is inherently ephemeral and local, so tracking it in Redux (or any kind of Flux library) is unnecessary
  2. Redux-Form calls your entire top-level Redux reducer multiple times ON EVERY SINGLE KEYSTROKE. This is fine for small apps, but as your Redux app grows, input latency will continue to increase if you use Redux-Form.
  3. Redux-Form is 22.5 kB minified gzipped (Formik is 7.8 kB)


My goal with Formik was to create a scalable, performant, form helper with a minimal API that does the really really annoying stuff, and leaves the rest up to you.

Use React for ephemeral state that doesn‘t matter to the app globally and doesn‘t mutate in complex ways. For example, a toggle in some UI element, a form input state. Use Redux for state that matters globally or is mutated in complex ways. For example, cached users, or a post draft.

Sometimes you‘ll want to move from Redux state to React state (when storing something in Redux gets awkward) or the other way around (when more components need to have access to some state that used to be local).

The rule of thumb is: do whatever is less awkward.
Dan Abramov(gaearon)
Working on @reactjs. Co-author of Redux and Create React App. Building tools for humans.From London, UK

Influences



Formik started by expanding on this little higher order component by Brent Jackson, some naming conventions from Redux-Form, and (most recently) the render props approach popularized by React-Motion and React-Router 4. Whether you have used any of the above or not, Formik only takes a few minutes to get started with.

Installation

Add Formik to your project.

npm i formik --save

示例

  • Basics
  • Sync Validation
  • Building your own input primitives
  • Working with 3rd-party inputs #1: react-select
  • Working with 3rd-party inputs #2: Draft.js
  • Accessing React lifecycle functions
  • React Native

The gist
Formik keeps track of your form‘s state and then exposes it plus a few reusable methods and event handlers (handleChange, handleBlur, and handleSubmit) to your form via props. handleChange and handleBlur work exactly as expected--they use a name or id attribute to figure out which field to update.

There are two ways to use Formik:

withFormik(): A Higher-order Component (HoC) that accepts a configuration object
<Formik />: A React component with a render prop
Both do exactly the same thing and share the same internal implementation. They just differ in their respective style....

// Higher Order Component
import React from ‘react‘;
import { withFormik } from ‘formik‘;

// Our inner form component which receives our form‘s state and updater methods as props
const InnerForm = ({
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit,
isSubmitting,
}) => (
<form onSubmit={handleSubmit}>
<input
type="email"
name="email"
onChange={handleChange}
onBlur={handleBlur}
value={values.email}
/>
{touched.email && errors.email && <div>{errors.email}</div>}
<input
type="password"
name="password"
onChange={handleChange}
onBlur={handleBlur}
value={values.password}
/>
{touched.password && errors.password && <div>{errors.password}</div>}
<button type="submit" disabled={isSubmitting}>
Submit
</button>
</form>
);

// Wrap our form with the using withFormik HoC
const MyForm = withFormik({
// Transform outer props into form values
mapPropsToValues: props => ({ email: ‘‘, password: ‘‘ }),
// Add a custom validation function (this can be async too!)
validate: (values, props) => {
const errors = {};
if (!values.email) {
errors.email = ‘Required‘;
} else if (br/>!/^[A-Z0-9._%+-][email protected][A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
) {
errors.email = ‘Invalid email address‘;
}
return errors;
},
// Submission handler
handleSubmit: (
values,
{
props,
setSubmitting,
setErrors / setValues, setStatus, and other goodies /,
}
) => {
LoginToMyApp(values).then(
user => {
setSubmitting(false);
// do whatevs...
// props.updateUser(user)
},
errors => {
setSubmitting(false);
// Maybe even transform your API‘s errors into the same shape as Formik‘s!
setErrors(transformMyApiErrors(errors));
}
);
},
})(InnerForm);

// Use <MyForm /> anywhere
const Basic = () => (
<div>
<h1>My Form</h1>
<p>This can be anywhere in your application</p>
<MyForm />
</div>
);

export default Basic;
// Render Prop
import React from ‘react‘;
import { Formik } from ‘formik‘;

const Basic = () => (
<div>
<h1>My Form</h1>
<p>This can be anywhere in your application</p>
{/*
The benefit of the render prop approach is that you have full access to React‘s
state, props, and composition model. Thus there is no need to map outer props
to values...you can just set the initial values, and if they depend on props / state
then--boom--you can directly access to props / state.
The render prop accepts your inner form component, which you can define separately or inline
totally up to you:

  • &lt;Formik render={props =&gt; &lt;form&gt;...&lt;/form&gt;}&gt;
  • &lt;Formik component={InnerForm}&gt;
  • &lt;Formik&gt;{props =&gt; &lt;form&gt;...&lt;/form&gt;}&lt;/Formik&gt; (identical to as render, just written differently)
    /}
    <Formik
    initialValues={{
    email: ‘‘,
    password: ‘‘,
    }}
    validate={values => {
    // same as above, but feel free to move this into a class method now.
    let errors = {};
    if (!values.email) {
    errors.email = ‘Required‘;
    } else if (br/>!/^[A-Z0-9._%+-][email protected][A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
    ) {
    errors.email = ‘Invalid email address‘;
    }
    return errors;
    }}
    onSubmit={(
    values,
    { setSubmitting, setErrors /
    setValues and other goodies */ }
    ) => {
    LoginToMyApp(values).then(
    user => {
    setSubmitting(false);
    // do whatevs...
    // props.updateUser(user)
    },
    errors => {
    setSubmitting(false);
    // Maybe transform your API‘s errors into the same shape as Formik‘s
    setErrors(transformMyApiErrors(errors));
    }
    );
    }}
    render={({
    values,
    errors,
    touched,
    handleChange,
    handleBlur,
    handleSubmit,
    isSubmitting,
    }) => (
    <form onSubmit={handleSubmit}>
    <input
    type="email"
    name="email"
    onChange={handleChange}
    onBlur={handleBlur}
    value={values.email}
    />
    {touched.email && errors.email && <div>{errors.email}</div>}
    <input
    type="password"
    name="password"
    onChange={handleChange}
    onBlur={handleBlur}
    value={values.password}
    />
    {touched.password && errors.password && <div>{errors.password}</div>}
    <button type="submit" disabled={isSubmitting}>
    Submit
    </button>
    </form>
    )}
    />
    </div>
    );

export default Basic;

Complementary Packages

As you can see above, validation is left up to you. Feel free to write your own validators or use a 3rd party library. Personally, I use Yup for object schema validation. It has an API that‘s pretty similar Joi / React PropTypes but is small enough for the browser and fast enough for runtime usage. Because I ?? Yup sooo much, Formik has a special config option / prop for Yup called validationSchema which will automatically transform Yup‘s validation errors into a pretty object whose keys match values and touched. Anyways, you can install Yup from npm...

npm install yup --save

(未完待续...)

参考资料

1.https://github.com/jaredpalmer/formik
2.
http://www.lizhe.name/node/252
3.
https://keyholesoftware.com/2017/10/23/the-joy-of-forms-with-react-and-formik/
4.

原文地址:http://blog.51cto.com/zhuxianzhong/2151661

时间: 2024-10-04 01:05:19

使用Formik轻松开发更高质量的React表单(一)入门的相关文章

使用Formik轻松开发更高质量的React表单(四)其他几个API解析

(下面部分内容正处于翻译中,敬请稍等......) <Field /> <Field /> will automagically hook up inputs to Formik. It uses the name attribute to match up with Formik state. <Field /> will default to an <input /> element. To change the underlying element o

移动Web—CSS为Retina屏幕替换更高质量的图片

来源:互联网 作者:佚名 时间:12-24 10:37:45 [大 中 小] 点评:Retian似乎是屏幕显示的一种趋势,这也是Web设计师面对的一个新挑战;移动应用程序的设计师们已经学会了如何为Retina屏幕设备显示更好质量的图片,用来提高用户的体验;在本文中,你将看到如何使用CSS3技巧在Web应用中为Retina屏幕替换更高质量的图片 特别声明:此篇文章根据Stéphanie Walter 的英文文章<The Mobile Web: CSS Image Replacement for R

【jeecg移动开发能力】表单移动开发能力,提供多套表单模板(移动端、PC端),支持自定义

[一].请假表单风格(单表)  [1]移动端风格 [2]PC端风格一   [3]PC端风格二    [二].订单管理表单风格(一对多)  [1]移动端风格 [2]PC端风格一  [3]PC端风格二

通过FormData对象可以组装一组用 [XMLHttpRequest]发送请求的键/值对,它可以更灵活方便的发送表单数据。

工作记录用 1 大概页面,点击选择按钮,选择文件,填写备注并可以上传前预览,然后点击上传按钮开始上传 2 html+js代码 <h2>Test</h2> <div id="fileList"></div> <span id="file_ct" style="display:none"><input id="file_input" accept="Ima

基于vue开发的一款强大的表单设计器,支持element和antd-vue表单快速开发。

基于 vue 和 element-ui 实现的表单设计器,使用了最新的前端技术栈,内置了 i18n 国际化解决方案,支持生成element 和 antd-vue 表单,让表单开发简单而高效. 在线预览 使用文档 特性 可视化配置页面 提供栅格布局,并采用flex实现对齐 一键预览配置的效果 一键生成配置json数据 一键生成代码,立即可运行 提供自定义组件满足用户自定义需求 提供远端数据接口,方便用户需要异步获取数据加载 提供功能强大的高级组件 支持表单验证 快速获取表单数据 国际化支持 组件

编写高质量代码改善C#程序的157个建议——建议30:使用LINQ取代集合中的比较器和迭代器

建议30:使用LINQ取代集合中的比较器和迭代器 LINQ提供了类似于SQL的语法来实现遍历.筛选与投影集合的功能. static void Main(string[] args) { List<Salary> companySalary = new List<Salary>() { new Salary() { Name = "Mike", BaseSalary = 3000, Bonus = 1000 }, new Salary() { Name = &qu

整套高质量前端基础到高级视频教程免费发布

我自己是从农村出来的,看到很多农村的寒门子弟初入社会,很难改变自身命运.尤其是很多大学生学习IT专业,但是大学期间荒废度日.很难从事IT行业,所以造就了目前IT培训市场的繁荣. 目睹了,大量的学生因为没有钱而享受不了高质量的IT培训的资源,我心里痛快至极.传智的工作越来越离着学员远,内心焦躁不已.自己深感,背离初心已远.毅然决然的放弃稳定的工作,从此自由身. 专心的为寒门子弟做点事情,为寒门子弟改变命运而做免费的高质量的IT入门学习资源,就是本真的我,就是我人生价值所在,依稀记得自己愿望,不忘初

react之form表单工具:formik+yup

从网上搜到的form表单解决方案如下: 1.uform,地址:https://uformjs.org/#/MpI2Ij/dNFzFyTb UForm 和核心特性: 基于标准 JSON Schema 协议,数据化构建表单 基于 rxjs 对表单内部的副作用做统一管理,轻松解决各种复杂联动校验场景 支持各种表单布局方案 支持可视化构建表单 支持自定义组件扩展 分布式状态管理,表单性能更高 不足:基于styled-components来开发的,涉及到的自定义样式主要是Form和FormItem层面上的

利用jquery.validate以及bootstrap的tooltip开发气泡式的表单校验组件

表单校验是页面开发中非常常见的一类需求,相信每个前端开发人员都有这方面的经验.网上有很多成熟的表单校验框架,虽然按照它们默认的设计,用起来没有多大的问题,但是在实际工作中,表单校验有可能有比较复杂的个性化的需求,使得我们用这些插件的默认机制并不能完成这些功能,所以要根据自己的需要去改造它们(毕竟自己还不到那个写一个完美的校验框架的层次).我用过formValidation这个校验框架,虽然它跟bootstrap配合地很好,但是校验风格太死板,不太满足个性化的场景:后来我找到了jquery.val