1

I'm trying to build a Password validator. My issue is that the boolean valid is always false even when the regex is tested to be correct. I am actually using typescript in my app, but I've made a demo here just in JSX:

https://codesandbox.io

The App.js file looks like this:

import React, { useState } from "react";
import "./styles.css";

const App = () => {
  const [inputValue, setInputValue] = useState('');
  const [valid, setValid] = useState(false);
  const isValidPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$@!%&*?])[A-Za-z\d#$@!%&*?]{12,}$/;
  //const isValidPasswordRegex = /^\d+$/;

  const validatePassword = (value) => {
    if (!isValidPasswordRegex.test(value)) {
      setValid(!valid);
    } else {
      setValid(valid);
    }
    return valid;
  };

  function onChange(e) {
    setInputValue(e.target.value);
    setValid(validatePassword(e.target.value));
  }
  
  return(
    <div>
      <div>Fill the password input and click elsewhere to blur the field</div>
      <input
        className={`${valid ? 'success' : 'error'}`}
        onChange={onChange}
        onBlur={onBlur}
        value={inputValue}
      />
      <div>{valid.toString()}</div>
    </div>
  );
}

export default App;

I've looked ay many similar questions on SO that seem to be using a very similar logic, but I assume that the app is re-rendering and valid is being set to false on each render. I thought useState was the correct implementation and binding this to an onChange event would test the input value each time it is changed. I was concerned my regex was not correct so I also tested a simpler condition (which is commented out here) but that is not the issue.

1 Answer 1

1

There are two problems with your code.

1.) validatePassword uses the useState's setter, but as a value to set it is using the valid state (e.g. setValid(!valid)). As useState's setter works asynchronously, this will not use the "latest" state. Just use true or false directly, no reason to use valid. That way you're also safe if valid is changed somewhere else in the code.

2.) In your onChange, you're calling validatePassword, which therefore is always setting the value of valid to false (or void, your example at StackOverflow differs from your example of the CodeSandbox), because you're calling validatePassword in your setValid.

Just call validatePassword(...) instead of setValid(validatePassword(...)), as validatePassword is already calling setValid:

  function onChange(e) {
    setInputValue(e.target.value);
    setValid(validatePassword(e.target.value));
  }

should be

  function onChange(e) {
    setInputValue(e.target.value);
    validatePassword(e.target.value);
  }

Another option would be to return true or false from validatePassword and don't call setValid inside there, but outside with the return value of validatePassword.


Working CodeSandbox: https://codesandbox.io/s/patient-worker-7fs84

I don't understand your regex, so I replaced it with a simple "every character is a letter" for demonstration purposes.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. I'd figured out the onChange event should be validatePassword(e.target.value); but returning valid was driving me around the bend. I am not entering a different world of regex hell. Thank you
Now entering! Sorry

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.