简体   繁体   中英

Hi, i'm retrieving data from firestore, and checking whether to direct the user to index page or to enter details for a new user But not able to do so

React code

    import React, { useEffect, useState } from "react";
    import { getDocs, collection } from "firebase/firestore";
    import { auth, db } from "../firebase-config";
    import { useNavigate } from "react-router-dom";
    
    function Load() {
      const navigate = useNavigate();
    
      const [accountList, setAccountList] = useState([]);
      const [hasEmail, setHasEmail] = useState(false);
      const accountRef = collection(db, "accounts");

Am i using useEffect correctly?

      useEffect(() => {
        const getAccounts = async () => {
          const data = await getDocs(accountRef);
          setAccountList(
            data.docs.map((doc) => ({
              ...doc.data(),
              id: doc.id,
            }))
          );
        };
        getAccounts();
        emailCheck();
        direct();
      }, []);

checking whether email exists

      const emailCheck = () => {
        if (accountList.filter((e) => e.email === auth.currentUser.email)) {
          setHasEmail(true);
        } else {
          setHasEmail(false);
        }
      };

Redirecting based on current user

      const direct = () => {
        if (hasEmail) {
          navigate("/index");
        } else {
          navigate("/enterdetails");
        }
      };
      return <div></div>;
    }

The code compiles but doesn't redirect properly to any of the pages. What changes should I make? First question posted excuse me if format is wrong.

There are two problems here:

useEffect(() => {
  const getAccounts = async () => {
    const data = await getDocs(accountRef);
    setAccountList(
      data.docs.map((doc) => ({
        ...doc.data(),
        id: doc.id,
      }))
    );
  };
  getAccounts();
  emailCheck();
  direct();
}, []);

In order:

  1. Since getAccounts is asynchronous, you need to use await when calling it.
  2. But even then, setting state is an asynchronous operation too, so the account list won't be updated immediately after getAccounts completes - even when you use await when calling it.

If you don't use the accountList for rendering UI, you should probably get rid of it as a useState hook altogether, and just use regular JavaScript variables to pass the value around.

But even if you use it in the UI, you'll need to use different logic to check its results. For example, you could run the extra checks inside the getAccounts function and have them use the same results as a regular variable:

useEffect(() => {
  const getAccounts = async () => {
    const data = await getDocs(accountRef);
    const result = data.docs.map((doc) => ({
      ...doc.data(),
      id: doc.id,
    }));
    setAccountList(result);
    emailCheck(result);
    direct();
  };
  getAccounts();
}, []);

const emailCheck = (accounts) => {
  setHasEmail(accounts.some((e) => e.email === auth.currentUser.email));
};

Alternatively, you can use a second effect that depends on the accountList state variable to perform the check and redirect:

useEffect(() => {
  const getAccounts = async () => {
    const data = await getDocs(accountRef);
    setAccountList(
      data.docs.map((doc) => ({
        ...doc.data(),
        id: doc.id,
      }))
    );
  };
  getAccounts();
});
useEffect(() => {
  emailCheck();
  direct();
}, [accountList]);

Now the second effect will be triggered each time the accountList is updated in the state.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM