Search code examples
javascriptreactjsreact-hooksrender

Can't understand the difference between username length in the state and in the input


How can I synchronize the regexp test validation with rendering, because it seems like for example if the validation regexp allows 5 characters, it will turn true when I have already 6 characters in the input field. It seems to me like it has something to do with rendering states.

username state:

const [username, setUsername] = useState({
    name: "",
    isValid: false,
  });

handle username function:

  function handleUsername(e) {
    const regexp = new RegExp(/[a-zA-Z][a-zA-Z0-9-_]{5,32}/gi);
    const isValid = regexp.test(username.name);
    setUsername(() => {
      return {
        name: e,
        isValid: isValid ? true : false,
      };
    });
    console.log("isValid - ",
      isValid,
      "|",
      "username.name.length - ",
      username.name.length); // => isValid -  false | username.name.length -  5
  }

run console.log outside the function:

console.log(
      "username.name.length - ",
      username.name.length); // => username.name.length -  6

I tried to figure out why this actually happen but it ends up with more confusions.


Solution

  • setState acts async, so you are console.logging the stale state.

      function handleUsername(e) {
        const regexp = new RegExp(/[a-zA-Z][a-zA-Z0-9-_]{5,32}/gi);
        const isValid = regexp.test(username.name);
        setUsername(() => {
          return {
            name: e,
            isValid: true,
          };
        });
        console.log("isValid - ",
          isValid,
          "|",
          "e.length - ",
          e.length); // => isValid -  false | e.length -  6
      }
    

    Either use the variable that defines the new state, or console.log it in the useEffect with username dependency

    useEffect(() => {
    console.log(username.name.length)
    
    }, [username])