【问题标题】:Password and Confirm Password validation on input with Joi使用 Joi 进行输入时的密码和确认密码验证
【发布时间】:2020-11-24 23:00:18
【问题描述】:

我在 React 中使用joi-browser 进行表单验证。我面临的问题是在输入时验证passwordconfirmPassword

我使用的架构与另一个 stackoverflow question 中提供的架构相同。

password: Joi.string().min(3).max(15).required(),
confirmPassword: Joi.any().valid(Joi.ref('password')).required().options({ language: { any: { allowOnly: 'must match password' } } })

一旦我开始输入confirmPassword,我的错误就会出现,即使它与password 相同,并且在提交时它会消失并提交表单。但如果confirmPassword 不一样,提交失败也没关系。

我想要的是,它应该在 onChange 事件上验证,如果 confirmPassword 字段与 password 字段匹配,则必须删除错误。

代码逻辑是,状态中的所有字段都定义在formData中,所有错误都会存储在state.errors中的同名对象errors中。如果出现错误,则在错误对象中创建条目,否则将其从错误对象中删除。

我的表单状态是:

state = {
    formData: {
        password: '',
        confirmPassword: ''
    },
    errors: {}
}

onChange方法是:

onChangeField = ({ currentTarget: input }) => {
    const errors = { ...this.state.errors };
    const errorMsg = this.validateField(input);
    if (errorMsg) errors[input.name] = errorMsg;
    else delete errors[input.name];

    const formData = { ...this.state.formData };
    formData[input.name] = input.value;
    this.setState({ formData, errors });
}
validateField = ({ name, value }) => {
    const obj = { [name]: value };
    const schema = { [name]: this.schema[name] };
    const { error } = Joi.validate(obj, schema);
    return error ? error.details[0].message : null;
};

【问题讨论】:

    标签: reactjs validation joi


    【解决方案1】:

    我遇到了同样的问题。这都是因为异步和等待模式。如果您将日志记录添加到案例中,您会看到它没有设置 onChangeField 状态。例如。它正在异步执行此操作。我还没有弄清楚最好的情况,但如果你添加一个完整的验证并等待状态设置,它就可以工作。

    例如我添加了类似的内容:

    onChangeField = async ({ currentTarget: input }) => {
    const errors = { ...this.state.errors };
    const errorMsg = this.validateField(input);
    if (errorMsg) errors[input.name] = errorMsg;
    else delete errors[input.name];
    
    const formData = { ...this.state.formData };
    formData[input.name] = input.value;
    
    await this.setState({ data, errors });
    
    
    if(!this.validate()){
        console.log(true);
        this.setState({ errors: {} });
    }
    

    }

    【讨论】:

    • 你不需要使用 async/await,因为 setState 有第二个边界,它是回调函数,在设置新状态后会执行。 setState({ data, errors } , ()=>{ console.log('State updated', this.state) });
    • 是的,但是您仍然需要添加if(!this.validate()){ console.log(true); this.setState({ errors: {} });,否则它对我不起作用,为此还需要添加回调函数,所以在我看来使用 async 和 await 更容易。除非你有不同的做法,如果是这样,你介意分享吗?
    • 我在Joi 中发现了很多限制,在我的表单中也很少有自定义要求,例如如果选中字段 A,则使字段 B 成为可选/必需等,而在 Joi 中,很难创建那种奇怪的支票。我开始使用另一个库Yup,它具有相同的功能但具有扩展功能。我从未从这个库中发现任何错误/限制。它与 Joi 有相同的模式,但它有大量的文档。在这里你可以开始codechips.me/svelte-form-validation-with-yup
    【解决方案2】:

    问题出在validateField 方法中,特别是在验证字段confirmPassword 时使用的Joi 模式中。在此模式中,还需要为 password 字段添加验证规则。所以你需要把validateField 方法改成这样:

    validateField = ({ name, value }) => {
     if (name === "confirmPassword") {
          const { formData} = this.state;
          const obj = { password: formData.password, [name]: value };
          const schema = {
            [name]: this.schema[name],
            password: this.schema["newPassword"],
          };
          const { error } = Joi.validate(obj, schema);
          return error ? error.details[0].message : null;
        }else{
         const obj = { [name]: value };
        const schema = { [name]: this.schema[name] };
        const { error } = Joi.validate(obj, schema);
        return error ? error.details[0].message : null;
    }
    };
    

    【讨论】:

      猜你喜欢
      • 2015-07-01
      • 2019-12-09
      • 2017-02-04
      • 2013-09-18
      • 2020-12-23
      • 2017-07-26
      • 1970-01-01
      • 1970-01-01
      • 2018-12-25
      相关资源
      最近更新 更多