Search code examples
node.jsreactjsreact-router-dom

react-router-dom useEffect dependency


I'm trying to validate a JWT token on component render, if found in localStorage

Im doing this using a useEffect() hook, and a useNavigate() hook from the react-router-dom library. Here is the code:

const navigate = useNavigate();

  useEffect(() => {
    try {
      const bbw = localStorage.getItem('bbw');
  
      const decodedToken = decodeToken(bbw);
      const decodedNumber = decodedToken.phoneNumber;
      setPhoneNumber(decodedNumber);
  
      const bbwVerify = isExpired(bbw);
      setValid(!bbwVerify);
    } catch (error) {
      console.error(error);
      navigate('/');
    }
  }, [navigate]);

Console Error:

You should call navigate() in a React.useEffect(), not when your component is first rendered.

I have tried to add the setPhoneNumber state variable to the dependency array to see if it changed anything, but it hasn't. I have also tried adding a timeout for the navigate() function call. Defining navigate within the useEffect hook leads to more errors.

Additional error, given that navigate() is not in the dependency array:

React Hook useEffect contains a call to 'setPhoneNumber'. Without a list of dependencies, this can lead to an infinite chain of updates. To fix this, pass [navigate] as a second argument to the useEffect Hook

Notes:

A window.location.href call is not a solution. I'm thinking that a useCallback hook could be a solution, but I have not been able to implement it for navigate().


Solution

  • The issue was due to the way I was handling my return() statement.

    Here is what I had before:

    return validated ? (
        <div className="c-wrapper a-wrapper">
          {/* return code */}
        </div>
      ) : navigate("/");
    

    Here is how I fixed it:

    return validated ? (
        <div className="c-wrapper a-wrapper">
          {/* return code */}
        </div>
      ) : <></>
    

    Simple solution to something I did not notice at the end of my code.