Home > Blockchain >  React: i have multiple conditions in a function, but only the last condition is took into account
React: i have multiple conditions in a function, but only the last condition is took into account

Time:10-04

I have a function which is triggered "onChange" on a password input. On every "onChange" event, I check if the password match with 4 conditions and if a condition matches, I set the corresponding state. This is my state const:

  const [passwordFlag, setPasswordFlag] = useState({
    length: false,
    min: false,
    maj: false,
    num: false,
    special: false,
  });

and this is my function:

 const checkPassword = (password) => {
      if (password.length >= 10) {
        setPasswordFlag({ ...passwordFlag, length: true });
      } else setPasswordFlag({ ...passwordFlag, length: false });
  
      if (password.match(/[a-z]/, "g"))
        setPasswordFlag({ ...passwordFlag, min: true });
      else setPasswordFlag({ ...passwordFlag, min: false });
  
      if (password.match(/[A-Z]/, "g"))
        setPasswordFlag({ ...passwordFlag, maj: true });
      else setPasswordFlag({ ...passwordFlag, maj: false });
  
      if (password.match(/[0-9]/, "g"))
        setPasswordFlag({ ...passwordFlag, num: true });
      else setPasswordFlag({ ...passwordFlag, num: false });
   };

The problem is that every time, this is only the last condition which is verified on an "onChange" event. In this example, my function will set the passwordFlag. num to "true" if there is a number in the password, but it will ignore the other condition. If I remove the number verification, this will be only the UPPERCASE which will be verify.

I have try switch case but I can't verify all this condition in a switch case, or I haven't found how do this.

How can I fix this?

CodePudding user response:

Every time you you set state, it triggers rerender. React sees that you try to setState multiple times. To optimize React just calls the last one. You need to combine all the conditions into one. So that you can call setState only once.

CodePudding user response:

I would suggest you to avoid updating state in every IF/Else conditions and put it at the end.

let res = {};
if (password.length >= 10) {
    res.length = true;
else if(password.match(/[a-z]/, "g")) {
    res.min = true;
}
else if(password.match(/[A-Z]/, "g")) {
    res.maj = true;
} 
else if(password.match(/[0-9]/, "g")) {
    res.num = true;
} 
else {
    res.length = false;
    res.min = true;
    res.maj = false;
    res.num = false;   
}
setPasswordFlag({...passwordFlag, ...res})

CodePudding user response:

I don't think keeping each of them as the state is a good approach.

How about we only keep one state, which is the password, and derive all the other flags from it? Seems cool right!

So your React code should be something like this:

import { useState } from "react";

function App() {
  const [password, setPassword] = useState("");

  let flags = {
    length: false,
    min: false,
    maj: false,
    num: false,
    special: false,
  };

  if (password.length > 10) {
    flags.length = true;
  }
  if (password.match(/[a-z]/, "g")) {
    flags.min = true;
  }
  if (password.match(/[A-Z]/, "g")) {
    flags.maj = true;
  }
  if (password.match(/[0-9]/, "g")) {
    flags.num = true;
  }

  // Do things with the flags:
  return (
    <div>
      <p>Values of Flags</p>
      <ul>
        <li>flags.length: {flags.length ? "TRUE" : "false"}</li>
        <li>flags.min: {flags.min ? "TRUE" : "false"}</li>
        <li>flags.maj: {flags.maj ? "TRUE" : "false"}</li>
        <li>flags.num: {flags.num ? "TRUE" : "false"}</li>
      </ul>
      <input
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Enter Password"
      />
    </div>
  );
}

export default App;

Keep in mind: Even though we did not keep the flags as state, the flags will sync with the state because each time password is updated, flags will be recalculated using the updated password.

  • Related