在 React 中使用 Joi 模式进行密码匹配验证不起作用

问题描述

我想在 React 中创建一个密码更改表单。这是我的组件的代码

import React,{ Component } from "react";
import Joi from "joi-browser";
import "./Login/Login.css";
import { UAA } from "../../Actions/Types";

class ChangePassword extends Component {
  state = {
    account: {
      currentPassword: "",newPassword: "",newPasswordRepeated: "",},errors: {},auth: UAA,};

  schema = {
    currentPassword: Joi.string().required().label("Password"),newPassword: Joi.string().min(12).max(64).required().label("Password"),newPasswordRepeated: Joi.any().valid(Joi.ref("newPassword")).required(),};

  validate = () => {
    const options = { abortEarly: false };
    const { error } = Joi.validate(this.state.account,this.schema,options);
    if (!error) return null;
    const errors = {};
    for (let item of error.details) {
      errors[item.path[0]] = item.message;
    }
    return errors;
  };

  validateProperty = ({ name,value }) => {
    const obj = { [name]: value };
    console.log(obj);
    const schema = { [name]: this.schema[name] };
    console.log(schema);
    const { error } = Joi.validate(obj,schema);
    console.log(JSON.stringify(error));
    return error ? error.details[0].message : null;
  };

  handleSubmit = (e) => {
    e.preventDefault();
    const errors = this.validate();
    this.setState({ errors: errors || {} });
    if (errors) return;
    //todo : call server
  };

  handleChange = ({ currentTarget: input }) => {
    const errors = { ...this.state.errors };
    const errorMessage = this.validateProperty(input);
    if (errorMessage) errors[input.name] = errorMessage;
    else delete errors[input.name];
    const account = { ...this.state.account };
    account[input.name] = input.value;
    this.setState({
      account: account,errors: errors,});
  };

  render() {
    const { errors,account } = this.state;
    return (
      <div className="container">
        <div className="col-md-5 offset-md-3">
          <form
            className="login-form"
            onSubmit={(event) => this.handleSubmit(event)}
          >
            <p />
            <p className="form-label">Current password</p>
            <input
              type="password"
              id="currentPassword"
              name="currentPassword"
              value={account.currentPassword}
              onChange={this.handleChange}
            />
            {errors.currentPassword && (
              <div className="alert alert-danger">{errors.currentPassword}</div>
            )}
            <p className="form-label">New password</p>
            <input
              type="password"
              name="newPassword"
              onChange={this.handleChange}
              value={account.newPassword}
            />
            {errors.newPassword && (
              <div className="alert alert-danger">{errors.newPassword}</div>
            )}
            <p className="form-label">Confirm password</p>
            <input
              type="password"
              name="newPasswordRepeated"
              value={account.newPasswordRepeated}
              onChange={this.handleChange}
            />
            {errors.newPasswordRepeated && (
              <div className="alert alert-danger">
                {errors.newPasswordRepeated}
              </div>
            )}
            <div className="submit-login-form">
              <input
                type="submit"
                value="Submit"
                disabled={this.validate()}
              ></input>
            </div>
          </form>
        </div>
      </div>
    );
  }
}

export default ChangePassword;

用户输入重复密码时,我想验证该重复密码是否与已输入的新密码匹配。这是在 validateProperty 方法中完成的。问题是 Joi 即使两个密码匹配也返回验证错误。我很感激这方面的任何帮助。

enter image description here

解决方法

经过一番研究,我能够找出问题所在。 问题在于验证字段 validateProperty 时使用的 Joi 架构中的方法 newPasswordRepeated。在此模式中,需要为 newPassword 添加验证规则。因此,我更改了我的 validateProperty 方法,如下所示:

validateProperty = ({ name,value }) => {
    if (name === "newPasswordRepeated") {
      const { account } = this.state;
      const obj = { newPassword: account.newPassword,[name]: value };
      const schema = {
        [name]: this.schema[name],newPassword: 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;
    }
  };

希望有人觉得这有用。