Home > OS >  React useEffect is returning empty data when page loads for the first time
React useEffect is returning empty data when page loads for the first time

Time:06-14

I am making an API call to firebase from useEffect and the data returned is empty when the page loads for the first time but gets populated if I make any changes to the code and save it. I want the data to be present when the page loads for the first time.

    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const [users, setUsers] = useState({});
    const [status, setStatus] = useState({});

    const userDetailsRef = collection(db, "userDetails");
    const userStatusRef = collection(db, "userStatus");

    const handleSubmit = (event) => {
        event.preventDefault();
        users.map((user) => {
            if (email === user.email && password === user.password) {
                getEmail();
            }
        });
    };
    const getEmail = async () => {
        const data = await getDocs(userStatusRef);
        setStatus(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
        console.log(status);
        status.map((em) => {
            if (email === em.email) {
                updateStatus(em.id);
            }
        });
    };
    const updateStatus = async (id) => {
        const userDoc = doc(db, "userStatus", id);
        const status = { status: "online" };
        await updateDoc(userDoc, status);
        console.log("updated status");
    };

    useEffect(() => {
        getUsers();
    }, []);
    const getUsers = async () => {
        const data = await getDocs(userDetailsRef);
        setUsers(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
        console.log(users);
    };

enter image description here

Because the data returned is empty, map function is throwing an error. But if I submit again it works as the data gets populated.

What should I change for the data to be fetched on the first page load?

CodePudding user response:

Setting the state in React acts like an async function.
Meaning that the when you set the state and put a console.log right after it, it will likely run before the state has actually finished updating.

Which is why we have useEffect, a built-in React hook that activates a callback when one of it's dependencies have changed.

Example:

useEffect(() => {
   console.log(users)
   // Whatever else we want to do after the state has been updated.
}, [users])

This console.log will run only after the state has finished changing and a render has occurred.

  • Note: "users" in the example is interchangeable with whatever other state piece you're dealing with.

Check the documentation for more info.

CodePudding user response:

setState is asynchronous, there's no guarantees that the state will be set by the time your log is hit.

See: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous

The state looks to be set correctly, your log statement just might not reflect pending state changes.

  • Related