redux-form:如何动态地排除一个同步验证器



我的redux-form修饰的表单组件有条件地有一个email字段,这取决于我的redux状态(取决于用户是否是来宾)

我只想在该字段存在时对其进行同步验证(有条件地呈现)。当前表单的验证器包括一个email字段验证器,并且这个验证器即使在render期间字段被排除在表单之外也会运行。

当我"实例化"表单的验证器时,当我将验证器作为参数传递给redux-form装饰器时,状态是未知的。因此,我目前无法决定是否包括email字段验证器,在这些地方。

基于状态,在"运行时"/"验证时间"动态包含/排除单个字段的redux-form验证器的最佳方法是什么?

MyForm.js

import validate from './MyFormValidator';
// [form class whose render optionally shows the email component]
export default reduxForm(
  {
    form: 'myForm',
    fields,
    validate
  }
)(MyForm)

MyFormValidator.js

import {createValidator, required, email} from '../../utils/validation';
export default createValidator({
  email: [email],
  country: [required],
  // ...
});

跑龙套/validation.js

export function email(value) {
  const emailRegex = /.../i;
  if (!emailRegex.exec(value)) {
    return 'Please provide a valid email address.';
  }
}
export function required(value, message) {
  if (isEmpty(value)) {
    return message || 'Required.';
  }
}
export function createValidator(rules) {
  return (data = {}) => {
    const errors = {};
    Object.keys(rules).forEach((key) => {
      const rule = join([].concat(rules[key]));
      const error = rule(data[key], data);
      if (error) {
        errors[key] = error;
      }
    });
    return errors;
  };
}

我的同步验证是按照这个实现建模的,链接到4.2.0 redux-form文档(我使用的是5.3.1):https://github.com/erikras/react-redux-universal-hot-example/blob/master/src/utils/validation.js

感谢@lewiscowper,他在一些JavaScript Slack上提出了这个解决方案。

由于输入是一个文本字段,因此如果呈现了输入,则该值将以空字符串的形式出现。

所以如果valuenull/undefined,我们可以跳过对字段的验证,因为我们知道它没有渲染。

为了避免验证器的误报用法,我将其重命名为emailUnlessNull

export function emailUnlessNull(value) {
  // Don't validate the text field if it's value is undefined (if it wasn't included in the form)
  if (value == null) {
    return;
  }
  const emailRegex = /.../i;
  if (!emailRegex.exec(value)) {
    return 'Please provide a valid email address.';
  }
}

最后,我认为一个完全排除验证器的解决方案——并且不使验证器的逻辑和使用复杂化——会好得多,但目前这是可行的。

很高兴接受更好的答案。

编辑:

您还必须确保,在optional-field-render场景中,您也将其值触发为空字符串。在它被触摸之前,它的值通过验证器作为null。

MyForm.js

componentWillReceiveProps(nextProps) {
  const { values, fields, isGuestOrder } = this.props;
  if (isGuestOrder && values.email == null) {
    fields.email.onChange('');
  }
}

如果你想考虑React-Redux-Form,这已经是内置的:

import { Field } from 'react-redux-form';
import { required, email } from '../../utils/validation';
// inside render():
<Field model="user.email"
  errors={{ email }}
/>

会发生两件事:

  • 错误验证器(在error中)将在每次更改时运行。您可以通过设置validateOn="blur"来修改此行为。
  • 验证只会在<Field>被渲染时发生。如果<Field>被卸载,该字段的验证将被重置。

最新更新