The Coder
The Coder

Reputation: 4017

Regex not working if the regex string is stored in a separate javascript file

I have a regex which validates the password provided by use in a form, the password must be 6 characters long, 1upper case, 1 lower case, 1 numerical and 1 special character.
Below is the react component for the form:

import React from "react";
import { passwordRegex } from "./Constants";

export default class App extends React.Component {
  constructor() {
    super();
    this.state = {
      email: null,
      password: null,
      disableSubmitButton: true
    };
  }

  formData = {
    email: "",
    password: ""
  };

  componentWillUpdate(nextProps, nextState) {
    nextState.disableSubmitButton = !(nextState.email && nextState.password);
  }

  initializeFormData = () => {
    this.formData = {
      email: this.state.email,
      password: this.state.password
    };
  };

  verifyFormData = () => {
    if (!passwordRegex.test(this.formData.password)) {
      console.error("invalid password");
      return false;
    }

    return true;
  };

  submitForm = event => {
    event.preventDefault();
    const ifFromValid = this.verifyFormData();
    console.log(ifFromValid);
  };

  render() {
    this.initializeFormData();
    return (
      <form onSubmit={this.submitForm}>
        <br />
        <label htmlFor="email">Email </label>
        <input
          type="text"
          onChange={event => {
            this.setState({ email: event.target.value });
          }}
        />
        <br />
        <label htmlFor="password" name="password">
          Password
        </label>
        <input
          type="password"
          onChange={event => {
            this.setState({ password: event.target.value });
          }}
        />
        <br />
        <input type="submit" name="submit" id="submit"
          disabled={this.state.disableSubmitButton}
        />
      </form>
    );
  }
}

Constants.js

export const passwordRegex = new RegExp(
  "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{6,}$",
  "g"
);

Problem:
The form validation works fine on the first submit, then on further submit clicks, the regex behave abnormally. Sometimes it enters to the if (!passwordRegex.test(this.formData.password)) block and sometimes doesn't enter.

The weird thing is: the same code works very perfectly if I create a local variable for passwrodRegex inside the verifyFormData() function:

      verifyFormData = () => {
        const passwordRegex = new RegExp("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{6,}$","g");
        if (!passwordRegex.test(this.formData.password)) {
          console.error("invalid password");
          return false;
        }

        return true;
      };

Upvotes: 2

Views: 2118

Answers (1)

Chris Lear
Chris Lear

Reputation: 6742

I think your problem is, bizarrely, the 'g' flag.

Try this:

passwordR = new RegExp("^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{6,}$","g");
console.log(passwordR.test('As!df2L$'));
console.log(passwordR.test('As!df2L$'));

The output will surprise you. It surprised me, anyway. (Spoiler, it's true false)

Now have a look at this: JavaScript RegExp cant use twice?

The headline is "RegExp instances have state when you use the g flag".

Finally, see if your code works as expected if you remove the g flag.

I've also found this, which has similar information: Why does a RegExp with global flag give wrong results?

Upvotes: 4

Related Questions