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);
};
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.