In short, you are trying to use the data from your asynchronous call before its ready.
To handle the case where your data hasn't finished loading, you should use:
console.log(trackscreenData && trackscreenData.data)
Based on the patterns in your code, you have these lines at the top of your component.
const { currentUserID } = useAuth(); // or similar const [userData, setUserData] = useState(); const [trackscreenData, setTrackScreenData] = useState(); // NOTE: check for typos: "trackscreenData" !== "trackScreenData"
On the first render of your code, trackscreenData will be undefined because you haven't passed an initial state into the useState() method.
const [trackscreenData, setTrackScreenData] = useState(/* initial state */);
// `trackscreenData` initially set to `null` const [trackscreenData, getTracksData] = useState(null); // `trackscreenData` initially set to `[]` const [trackscreenData, getTracksData] = useState([]); // `trackscreenData` initially set to the result of the function, // an array containing the elements 0 through 99. The function is // only executed once to set the first value. // trackscreenData = [0, 1, 2, 3, ... , 97, 98, 99]; const [trackscreenData, getTracksData] = useState(() => { Array.from({length: 100}) .map((_, i) => i); }
When React executes your code, any calls to setters returned from useState calls (e.g. setTrackScreenData) are queued. Only once your code has finished executing, are they evaluated and any new renders triggered.
const [count, setCount] = useState(0); // `count` is initially set to `0` useEffect(() => { if (count < 10) { setCount(count + 1); } }) console.log(count); console.log("rendered"); // Console logs: // > "0" // > "rendered" // > "1" // > "rendered" // > ... // > "9" // > "rendered" // > "10" // > "rendered"
Your fetch of user data should be in its own useEffect call and should return its unsubscribe function:
useEffect(() => { if (!currentUserUID) { setUserData(null); // user not signed in return; } // SNAPSHOT USER DATA return db.collection("users") // <- note the return here .doc(currentUserUID) .onSnapshot((doc) => { setUserData(doc.data()); }); }, [currentUserUID]);
useEffect(() => { let disposed = false; // Alleen preview async function getTracksData() { let TrackData = await firebase .firestore() .collection('TrackScreen') .doc('LeerjarenData') .get(); if (disposed) return; // component was removed, do nothing if (!TrackData.exists) { console.log('Geen data') } else { let TrackDatav2 = TrackData.data(); setTrackScreenData(TrackDatav2) } } getTracksData() .catch((err) => console.error(err)); // don't forget to handle errors! return () => disposed = true; // ignore result if component disposed }, []);