【问题标题】:Refactoring validation handling and messaging重构验证处理和消息传递
【发布时间】:2021-01-15 11:00:20
【问题描述】:

我正在开发一个使用 redux 表单的 react 项目。如果需要,我已经遍历了这些字段以检查它们的验证要求。这个堆栈运行良好 - 但我知道我应该重新访问它以将部件放入函数中

    if(field.validate.includes("email")) {
      //email
      if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values[fieldName])) {
        errors[fieldName] = 'Invalid email address'
      }
    }
    
    if(field.validate.includes("minLength")) {
      //minLength
      if (values[fieldName] !== undefined && values[fieldName].length < 3) {
        errors[fieldName] = 'Must be 3 characters or more'
      }
    }

    if(field.validate.includes("required")) {
      //required
      if (!values[fieldName] && typeof values[fieldName] !== "number") {
        errors[fieldName] = 'Required'
      }
    }

我试图编写一个看起来像这样的函数 - 但我不想破坏堆栈。

  messageHandler(field, validation, rule, message){
    if(field.validate.includes(validation)) {
      if (rule) {
        return message;
      }
    } 
  }

【问题讨论】:

  • 这个/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i 是非常糟糕 的电子邮件正则表达式...有些人住在其他国家,使用与A-Z 不同的字符...不要'使用这些正则表达式不会使人们的生活变得比应有的复杂。
  • 当时我只需要让一些工作正常 - 这个解决方案似乎工作正常。

标签: javascript reactjs validation


【解决方案1】:

据我所知,您正在尝试根据一组已定义的规则验证字段的内容。

对我来说,规则只是可以成功也可以不成功的功能。为简单起见,假设返回null 表示成功,否则返回错误消息(只是一个字符串)。

const rules = {
  email:     value => !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value) 
                  ? 'Invalid email address' 
                  : null,
  minLength: value => value !== undefined && value.length < 3
                  ? 'Must be 3 characters or more' 
                  : null,
  required:  value => !value && typeof value !== "number"
                  ? 'Required' 
                  : null,
};

现在,对于我们在field.validate 中找到的每条规则,我们将应用相应的规则并收集结果:

const matchingRules = field.validate
                        .map(formValidate => rules[formValidate])
                        .filter(x => x); // filter nullish values (rules that are not found)

const errors = matchingRules
                 .map(fn => fn(values[fieldName]))
                 .filter(x => x); // filter nullish values (successful rules)

现在,errors 包含一个字符串列表,描述该字段如何不符合不同的规则,当然,如果errors.length === 0,则测试成功。

您可以根据需要添加任意数量的规则,而无需重复所有 ifs。

【讨论】:

  • 不确定这是否按计划工作 - errors[fieldName] = 'Required' - 是错误数组的处理方式 - 但是当我查看您的版本中的错误时 - 它只提供 [ “必填”]
  • 当我尝试让错误出现时 - 无效的电子邮件地址必须是 3 个字符或更多字符 - 它会一次混合该字段的所有错误 - 而不是堆叠它们
  • 如果我做这样的事情 - 它似乎取代了功能 - const errorMsg = matchingRules .map(fn => fn(values[fieldName])) .filter(x => x) ; // 过滤空值(成功规则) if(errorMsg){ errors[fieldName] = errorMsg.reverse()[0]; }
  • errors 是一个包含所有遇到的错误的数组。如果您只想显示一个错误,您可以选择第一个错误。测试的执行顺序是数组field.validate的顺序
【解决方案2】:

在这个项目中引入另一个库是否可以接受?我喜欢使用joi 进行验证。当然,了解验证在后台的工作原理很重要,但您似乎对此掌握得很好。

以下是您如何使用当前代码实现此功能的示例:

首先,您将定义一个模式,它实质上代表了您填写的表单的理想最终状态。下面,我说表单值将包含一个email,这将是一个至少 3 个字符长的必需字符串。

const Joi = require('joi');

const schema = Joi.object({
   email: Joi.string().email().required().min(3)
})

然后,当您准备好验证表单数据时:

const validation = schema.validate({ email: 'foo@bar.com' });

validation 将包含值和错误(如果有的话)。

您可以将schema.validate 函数放入useEffect 中,该函数在用户更新输入时触发,或者您可以等到用户尝试提交表单,无论您的UI 需要什么。

我喜欢它,因为它易于读写,而且非常灵活。

【讨论】:

  • 这是可能的——我只是暂时不想添加更多的库——因为它已经是材料 ui 和 redux 表单的混合体
猜你喜欢
  • 1970-01-01
  • 2012-06-12
  • 2020-10-19
  • 2017-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多