I am trying to display data from a firestore database by pushing it to an array and mapping it. My goal is to have it display on the first page load, however, it only displays after I make changes to my code and I don’t know why. My suspicion is that it has something to do with the dataArray.push() not waiting for the fetch to finish, but I’m not sure. I’ll attach some images to show what I mean, I have tried fixing this but nothing works.
On first page load: https://i.stack.imgur.com/RM6sU.png
After editing the code: https://i.stack.imgur.com/u43We.png
import '../css/ClassBox.css'
import { db } from '../Firebase/firebase'
import { doc, getDoc } from 'firebase/firestore';
function ClassBox() {
const [dataArray, setDataArray] = useState([])
const [classesArray, setClassesArray] = useState([])
useEffect(() => {
const fetchUserData = async () => {
var tempArray = []
const userData = await getDoc(doc(db, 'users', localStorage.getItem('id')))
tempArray.push(userData.data().classes)
tempArray = tempArray.toString().replace(/s*,s*/g, ",").trim().split(",")
setClassesArray(tempArray)
}
const fetchClassData = async () => {
for(let i=0; i<classesArray.length; i++) {
let data = await getDoc(doc(db, 'classes', classesArray[i]))
dataArray.push(data.data())
}
console.log(dataArray)
}
fetchUserData()
.then(fetchClassData())
}, [])
return (
<div className='classBoxList'>
{dataArray.map((classes) => (
<div className='classBox'>
<div className='classBoxContainer'>
<div kclassName='classBoxWrapper'>
<div className='statusContainer'>
<h3>CS 106</h3>
<h4 key={classes.status}>{classes.status}</h4>
</div>
<div className='classInfoContainer'>
<ul>
<li key={classes.classCRN}>CS 106 - {classes.classCRN}</li>
<li key={classes.instructorName}>{classes.instructorName}</li>
<li key={classes.building}>{classes.building}</li>
<li key={classes.instructionMethod}>{classes.instructionMethod}</li>
<li key={classes.takenSeats}>Seats: {classes.takenSeats}/{classes.totalSeats}</li>
<li key={classes.remainingSeats}>Remaining: {classes.remainingSeats}</li>
</ul>
</div>
</div>
</div>
</div>
))}
</div>
)
}
export default ClassBox ```
2
Answers
You are incorrectly mutating the dataArray state variable using push. You should use setDataArray() instead.
First, inside .then (next to fetchUserData), you wrote a function call rather than a callback. Change it to .then(() => callback()) or .then(callback).
Second, state changes inside useEffect loop reflects changes only after the next render. So even after calling setClassesArray inside fetchUserData, fetchClassData will be called with the previous value of classesArray.
Third, you can’t push to dataArray directly, rather use setDataArray call only.
Try this: