Home > Software engineering >  How to use useNavigate outside react hook?
How to use useNavigate outside react hook?

Time:08-17

Gets list of emails from firestore and checks if current user is registered and then redirects them to sign up if they are new user.

The code is functional(it redirects succesfully) but get the following error: arning: Cannot update a component (BrowserRouter) while rendering a different component You should call navigate() in a React.useEffect(), not when your component is first rendered.

 const navigate = useNavigate();

  let hasEmail = false;
  const [emailList, setEmailList] = useState([]);
  const emailRef = collection(db, "emails");

  useEffect(() => {
    const getEmails = async () => {
      const data = await getDocs(emailRef);
      setEmailList(
        data.docs.map((doc) => ({
          ...doc.data(),
        }))
      );
    };
    getEmails();
  }, []);

  const emailCheck = (emails) => {                     //checks if email exists
    hasEmail = emails.some((e) => e.email === auth.currentUser.email);
  };
  const direct = () => {                         // redirects to required page
    if (hasEmail) {
      navigate("/index");
    } else {
      navigate("/enterdetails");
    }
  };
  emailCheck(emailList);
  direct();

CodePudding user response:

Move the email checking logic into a useEffect hook with a dependency on the emailList state.

const navigate = useNavigate();

const [emailList, setEmailList] = useState([]);
const emailRef = collection(db, "emails");

useEffect(() => {
  const getEmails = async () => {
    const data = await getDocs(emailRef);
    setEmailList(
      data.docs.map((doc) => ({
        ...doc.data(),
      }))
    );
  };
  getEmails();
}, []);

useEffect(() => {
  if (emailList.length) {
    const hasEmail = emailList.some((e) => e.email === auth.currentUser.email);
    navigate(hasEmail ? "/index" : "/enterdetails");
  }
}, [auth, emailList, navigate]);

CodePudding user response:

This might not run without the proper firebase config but check it out

https://codesandbox.io/s/elated-bell-kopbmp?file=/src/App.js

Things to note:

Use useMemo for hasEmail instead of emailCheck. This will re-run only when emailList changes

const hasEmail = useMemo(() => {
    //checks if email exists
    return emailList.some((e) => e.email === auth.currentUser.email);
 }, [emailList]);

There isn't really a point in having this in a react component if you are just redirecting away. Consider having the content of 'index' at the return (</>) part of this component. Only redirect if they aren't authorized

useEffect(() => {
  if (!hasEmail) {
    navigate("/enterdetails");
  } 
  //else {
  //  navigate("/index");
  //}
}, [hasEmail, navigate]);
  • Related