Reputation: 23
After getting the documents I want and storing as objects in an array shown here
const appealsRef = collection(db, "appeals");
const today = new Date();
const getAppeals = async (logicalOp) => {
const q = query(appealsRef, where("toDate", logicalOp, convertDateToTimestamp(today)))
const querySnapshot = await getDocs(q);
let dummyAppeals = [];
querySnapshot.docs.map((doc) => {
const docData = { ...doc.data() };
getOrgByDocID(docData.orgDocID)
.then((res) => {
const appealData = {
...docData,
orgName : res.orgName,
orgAddress : res.orgAddress
}
dummyAppeals.push(appealData)
})
});
return dummyAppeals
}
I would like to set the results in state variables currentAppeals
and pastAppeals
based on the logicalOp
given in useEffect
and then set it into another state variable array appeals using setAppeals
; this is because depending on what the user clicks on which is past or present I would like to set the appeals array to currentAppeals
if present is clicked or pastAppeals
if past is clicked.
The code involved :
const [ currentAppeals, setCurrentAppeals ] = useState([]);
const [ appeals, setAppeals ] = useState([]);
useEffect(() => {
getAppeals(">=")
.then((res) => {
setCurrentAppeals(res);
setAppeals(currentAppeals.map((appeal, i) => {
return (
<AppealCard
appealID={appeal.appealID}
from={appeal.fromDate}
to={appeal.toDate}
orgName={appeal.orgName}
orgAddress={appeal.orgAddress}
outcome={appeal.outcome}/>
)
}));
});
}, []);
And then I will display the appeals
in the react component here :
<div className='view-appealsBody'>
{
appeals
}
</div>
But the appeals
are not set after setAppeals
in useEffect()
.
Upvotes: 2
Views: 66
Reputation: 202618
getAppeals
doesn't wait for the dummyAppeals
array to become populated, it simply returns the empty array while the asynchronous code in the map callback runs.currentAppeals
is still the initial empty array value when the code tries to map it to JSX.Update getAppeals
to return the array of resolved promises containing the appeals
const appealsRef = collection(db, "appeals");
const today = new Date();
const getAppeals = async (logicalOp) => {
const q = query(appealsRef, where("toDate", logicalOp, convertDateToTimestamp(today)));
const querySnapshot = await getDocs(q);
return Promise.all(querySnapshot.docs.map((doc) => {
const docData = { ...doc.data() };
return getOrgByDocID(docData.orgDocID)
.then((res) => ({
...docData,
orgName : res.orgName,
orgAddress : res.orgAddress
}))
})
);
};
...
const [currentAppeals, setCurrentAppeals] = useState([]);
useEffect(() => {
getAppeals(">=").then((res) => setCurrentAppeals(res));
}, []);
return (
...
{currentAppeals.map((appeal, i) => (
<AppealCard
key={appeal.appealID}
appealID={appeal.appealID}
from={appeal.fromDate}
to={appeal.toDate}
orgName={appeal.orgName}
orgAddress={appeal.orgAddress}
outcome={appeal.outcome}/>
))}
...
);
Upvotes: 3
Reputation: 6830
It happens because React setState is an asynchronous function. You're setting appeals
using previously set state i.e currentAppeals
. Instead of try to set it using res
only like:
const [ currentAppeals, setCurrentAppeals ] = useState([]);
const [ appeals, setAppeals ] = useState([]);
useEffect(() => {
getAppeals(">=")
.then((res) => {
setCurrentAppeals(res);
setAppeals(res.map((appeal) => {
return (
<AppealCard
key={appeal.appealID}
appealID={appeal.appealID}
from={appeal.fromDate}
to={appeal.toDate}
orgName={appeal.orgName}
orgAddress={appeal.orgAddress}
outcome={appeal.outcome}/>
)
}));
});
}, []);
Upvotes: 0
Reputation: 991
you must set appeals as second parameter in useEffect
useEffect(() => {
getAppeals(">=")
.then((res) => {
setCurrentAppeals(res);
});
}, [appeals]);
and better put this code to return the body of component
currentAppeals.map((appeal, i) => {
return (
<AppealCard
appealID={appeal.appealID}
from={appeal.fromDate}
to={appeal.toDate}
orgName={appeal.orgName}
orgAddress={appeal.orgAddress}
outcome={appeal.outcome}/>
)
});
Upvotes: 0
Reputation: 922
Check this out
// const [ currentAppeals, setCurrentAppeals ] = useState([]);
const [ appeals, setAppeals ] = useState([]);
useEffect(() => {
getAppeals(">=")
.then((res) => {
// setCurrentAppeals(res);
setAppeals(res.map((appeal, i) => {
return (
<AppealCard
appealID={appeal.appealID}
from={appeal.fromDate}
to={appeal.toDate}
orgName={appeal.orgName}
orgAddress={appeal.orgAddress}
outcome={appeal.outcome}/>
)
}));
});
}, []);
Upvotes: 0