'Password matching validation using the Joi schema in React not working

I want to create a password change form in React. Here is the code of my component :

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;

When the user enters a repeated password, I want to validate whether that repeated password matches the new password already entered. This is done within the validateProperty method.The problem is that Joi returns validation error even if both passwords match. I appreciate any help with this. enter image description here



Solution 1:[1]

After some researching, I was able to figure out what was the problem. The problem lies in method validateProperty specifically in Joi schema used when validating the field newPasswordRepeated. In this schema, it is necessary to add a validation rule for newPassword. Therefore I changed my validateProperty method like below:

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;
    }
  };

Hope someone finds this useful.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1