Formik官方应用案例解析同步校验

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Formik官方应用案例解析同步校验相关的知识,希望对你有一定的参考价值。

简介

官方示例工程formik-09x-synchronous-validation-example展示的是基于Formik的表单开发中如何进行定制的同步校验的问题。

上一个实例相关内容回顾

回顾一下第一个示例Basics,其中有下面代码:

const EnhancedForm = withFormik({
  mapPropsToValues: () => ({ email: ‘‘ }),
  validationSchema: Yup.object().shape({
    email: Yup.string()
      .email(‘Invalid email address‘)
      .required(‘Email is required!‘),
  }),
  handleSubmit: (values, { setSubmitting }) => {
    setTimeout(() => {
      alert(JSON.stringify(values, null, 2));
      setSubmitting(false);
    }, 1000);
  },
  displayName: ‘BasicForm‘, // helps with React DevTools
})(MyInnerForm);

在上面代码片断中,理解mapPropsToValues属性的作用对于理解Formik全局有极为重要的意义。注意,在这里它返回了一个props对象(本例中是{ email: ‘‘ })。正是由于这一映射(即转换操作),才有了其他对应位置接下来的values.email(即props.values.email)引用。
其次,在实现表单数据校验方面,使用了下面代码:

validationSchema: Yup.object().shape({
    email: Yup.string()
      .email(‘Invalid email address‘)
      .required(‘Email is required!‘),
  }),

这个validationSchema是使用Yup这个开源JS校验工具库所要求的。注意到,在判断一个字符串是否是一个有效的Email地址时,它使用了内置于Yup库的判断方式(调用email()方法进行判定——而并没有使用原始的正则表达式判定方式。

【问题】这里预留一个问题供朋友们思考:上面Yup校验是同步的还是异步的?

定制的表单同步校验

本文案例给出的正是Formik支持下的表单同步校验支持方案。关键代码如下:

const MyEnhancedForm = withFormik({
  mapPropsToValues: () => ({ email: ‘‘ }),

  // Custom sync validation
  validate: values => {
    let errors = {};
    if (!values.email) {
      errors.email = ‘Required‘;
    } else if (
      !/^[A-Z0-9._%+-][email protected][A-Z0-9.-]+.[A-Z]{2,4}$/i.test(
        values.email
      )
    ) {
      errors.email = ‘Invalid email address‘;
    }
    return errors;
  },

  handleSubmit: (values, { setSubmitting }) => {
    setTimeout(() => {
      alert(JSON.stringify(values, null, 2));
      setSubmitting(false);
    }, 1000);
  },

  displayName: ‘BasicForm‘, // helps with React DevTools
})(MyForm);

其实,这里关键是理解validate这个属性(withFormik()方法的参数是一个可配置对象,validate则是该对象的属性之一)。根据官方文件介绍,这个属性是实现定制同步校验编程的关键思路。而且注意到,上面代码中使用非常原始的正则表达式方案校验电子邮件地址格式正确与否。
如果把这里的思路放开一些,即可以通过判定values.email,values.someotherfield......来进行其他众多的字段内容校验判定。也就是由于这一思路,我们注意到没有必要再和redux-form中那样实现专门的字段级别校验了。

异步校验

尽管官方没有给出完整独立的表单异步校验案例,但是官方文档再介绍withFormik的validate属性用法时一并提供了同步校验和异步校验的例子,不过都是使用了定制校验方式:

// Synchronous validation
const validate = (values, props) => {
  let errors = {};

  if (!values.email) {
    errors.email = ‘Required‘;
  } else if (!/^[A-Z0-9._%+-][email protected][A-Z0-9.-]+.[A-Z]{2,4}$/i.test(values.email)) {
    errors.email = ‘Invalid email address‘;
  }

  //...

  return errors;
};

// Async Validation
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));

const validate = (values, props) => {
  return sleep(2000).then(() => {
    let errors = {};
    if ([‘admin‘, ‘null‘, ‘god‘].includes(values.username)) {
      errors.username = ‘Nice try‘;
    }
    // ...
    if (Object.keys(errors).length) {
      throw errors;
    }
  });
};

其实,Formik作者极力推荐的Yup方案(结合validationSchema的使用)就是一种极其简洁的异步校验方案。当然,示例Basics中的代码比较隐蔽;更直观的异步校验代码片段如下:

const numSchema = yup.number();
const validator = (val) => {
  numSchema.validate(val)
    .then(result => {
      console.log(result); // it is the value of `val`
      return true;
    })
    .catch(error => {
      console.log(error.errors); // array of validation error messages
      return false;
    });
};

相信你能够轻松地把上面代码片段修改后添加到withFormik这个HOC函数代码当中。

引用

1,著名开源JS校验工具Yup(https://github.com/jquense/yup);
2,https://github.com/jaredpalmer/formik#validationschema-schema--props-props--schema
3,https://til.hashrocket.com/posts/35a5bwlxn7-yup-schemas-are-validated-asynchronously

以上是关于Formik官方应用案例解析同步校验的主要内容,如果未能解决你的问题,请参考以下文章

Formik官方应用案例解析组件生命周期事件

Formik官方应用案例解析使用react-select

Formik使用教程以及开发中遇到的问题

[react] 你有使用过formik库吗?说说它的优缺点

Express实战 - 应用案例- realworld-API - 路由设计 - mongoose - 数据验证 - 密码加密 - 登录接口 - 身份认证 - token - 增删改查API(代码片段

案例16-validate自定义校验规则校验用户名是否存在