繁体   English   中英

反应验证密码和确认密码字段

[英]React validate password and confirm password fields

我试图验证值passwordconfirmPassword如下字段。 问题是状态更新似乎滞后了一个事件(字符)。 例如:如果 password.value = "pass1234",验证时的 confirmPassword.value 是 "pass123",尽管已经输入了 "4"。 所以验证发生在状态更新之前。 解决这个问题的最佳方法是什么?

import React, { Component } from "react";
import { connect } from "react-redux";
import { Redirect } from "react-router-dom";

import Aux from "../../hoc/Aux/Aux";
import Button from "../../components/UI/Button/Button";
import Input from "../../components/UI/Input/Input";
import Spinner from "../../components/UI/Spinner/Spinner";
import classes from "./Auth.module.css";
import * as actions from "../../store/actions/index";

class Auth extends Component {
  state = {
    controls: {
      name: {
        elementType: "input",
        elementConfig: {
          placeholder: "name"
        },
        value: "",
        validation: {
          required: true,
          minLength: 4
        },
        valid: false,
        touched: false
      },
      email: {
        elementType: "input",
        elementConfig: {
          type: "email",
          placeholder: "Email ID"
        },
        value: "",
        validation: {
          required: true,
          isEmail: true
        },
        valid: false,
        touched: false
      },
      password: {
        elementType: "input",
        elementConfig: {
          type: "password",
          placeholder: "password"
        },
        value: "",
        validation: {
          required: true,
          minLength: 8
        },
        valid: false,
        touched: false
      },
      confirmPassword: {
        elementType: "input",
        elementConfig: {
          type: "password",
          placeholder: "confirm password"
        },
        value: "",
        validation: {
          required: true,
          minLength: 8,
          passwordMatch: true
        },
        valid: false,
        touched: false
      }
    },

    isSignup: false
  };

  checkValidity(value, rules) {
    let isValid = true;
    if (!rules) {
      return true;
    }

    if (rules.required) {
      isValid = value.trim() !== "" && isValid;
    }

    if (rules.minLength) {
      isValid = value.length >= rules.minLength && isValid;
    }

    if (rules.maxLength) {
      isValid = value.length <= rules.maxLength && isValid;
    }

    if (rules.isEmail) {
      const pattern = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
      isValid = pattern.test(value) && isValid;
    }

    if (rules.isNumeric) {
      const pattern = /^\d+$/;
      isValid = pattern.test(value) && isValid;
    }

    if (rules.passwordMatch) {
      const pwd = this.state.controls.password.value;
      console.log("pwd: " + pwd);
      console.log("pwdConfirm: " + this.state.controls.confirmPassword.value);
      isValid = this.state.controls.confirmPassword.value === pwd;
    }

    return isValid;
  }

  inputChangedHandler = (event, controlName) => {
    let updatedControls = {
      ...this.state.controls,
      [controlName]: {
        ...this.state.controls[controlName],
        value: event.target.value,
        valid: this.checkValidity(
          event.target.value,
          this.state.controls[controlName].validation
        ),
        touched: true
      }
    };
    this.setState({ controls: updatedControls });
  };

  submitHandler = event => {
    event.preventDefault();
    if (!this.state.isSignup) {
      this.props.onAuth(
        this.state.controls.email.value,
        this.state.controls.password.value,
        this.state.isSignup
      );
    } else {
      this.props.onSignUp(
        this.state.controls.name.value,
        this.state.controls.email.value,
        this.state.controls.password.value,
        this.state.controls.confirmPassword.value
      );
    }
  };

  switchAuthModeHandler = () => {
    this.setState(prevState => {
      return { isSignup: !prevState.isSignup };
    });
  };

  render() {
    const formElementsArray = [];
    if (!this.state.isSignup) {
      for (let key in this.state.controls) {
        if (key !== "name" && key !== "confirmPassword") {
          formElementsArray.push({
            id: key,
            config: this.state.controls[key]
          });
        }
      }
    } else {
      for (let key in this.state.controls) {
        formElementsArray.push({
          id: key,
          config: this.state.controls[key]
        });
      }
    }

    let form = null;
    form = formElementsArray.map(formElement => (
      <Input
        key={formElement.id}
        elementType={formElement.config.elementType}
        elementConfig={formElement.config.elementConfig}
        value={formElement.config.value}
        invalid={!formElement.config.valid}
        shouldValidate={formElement.config.validation}
        touched={formElement.config.touched}
        changed={event => this.inputChangedHandler(event, formElement.id)}
      />
    ));
    let button;
    if (!this.state.isSignup) {
      button = <button btnType="Success">LOGIN</button>;
    } else {
      button = <button btnType="Success">REGISTER</button>;
    }
    let buttonRegister = null;
    if (!this.state.isSignup) {
      buttonRegister = (
        <button btnType="SignUp" onClick={this.switchAuthModeHandler}>
          SIGN UP FREE!
        </button>
      );
    } else {
      buttonRegister = (
        <button btnType="SignUp" onClick={this.switchAuthModeHandler}>
          Back to Login!
        </button>
      );
    }

    if (this.props.loading) {
      form = <Spinner />;
    }

    let errorMessage = null;

    if (this.props.error && !this.state.isSignup) {
      errorMessage = <p>Email or Password is incorrect</p>;
    }

    if (this.props.error && this.state.isSignup) {
      errorMessage = <p>Please confirm email is valid and passwords match</p>;
    }

    if (this.props.error && this.state.isSignup) {
      let errorObj = JSON.parse(`${this.props.error}`);

      if (errorObj.code == "11000") {
        errorMessage = (
          <p>
            Email is already in use. Please reset your password, if you don't
            remember it
          </p>
        );
      }
    }

    let authRedirect = null;
    if (this.props.isAuthenticated) {
      authRedirect = <Redirect to={this.props.authRedirectPath} />;
    }

    return (
      <div className={classes.Auth}>
        {authRedirect}
        {errorMessage}
        <form onSubmit={this.submitHandler}>
          {form}
          {button}
        </form>
        {buttonRegister}
      </div>
    );
  }
}

const mapStateToProps = state => {
  return {
    loading: state.auth.loading,
    error: state.auth.error,
    isAuthenticated: state.auth.token !== null,
    role: state.auth.role,
    userName: state.auth.name,
    userPoints: state.auth.userPoints,
    userJourneyPoints: state.auth.userJourneyPoints,
    journeysCompleted: state.auth.journeysCompleted,
    userLevel: state.auth.userLevel,
    useHints: state.auth.useHints
  };
};

const mapDispatchToProps = dispatch => {
  return {
    onAuth: (email, password, isSignup) =>
      dispatch(actions.auth(email, password, isSignup)),
    onSignUp: (name, email, password, confirmPassword) =>
      dispatch(actions.signUp(name, email, password, confirmPassword))
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Auth);

浏览您的代码后,似乎您可以通过将target.event.value与由于更改“确认密码”输入而调用inputChangedHandlerpassword的当前状态进行比较来解决问题。 您当前正在做的是在confirmPassword有机会更新之前比较confirmPasswordpassword状态。 但是,“确认密码”输入的target.event.value将在调用inputChangedHandler时具有更新的值。

另一种解决方案可能是在componentDidUpdate内验证您的表单,而不是在调用inputChangedHandler立即验证。 通过在componentDidUpdate内部进行验证,您可以确保状态有时间更新。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM