const ID = useSelector((state) => state.userDetail.userID);
const [postItem, setpostItem] = useState([]);
useEffect(() => {
const q = query(
collection(firestore, "latestPost"),
where("userID", "==", ID)
);
onSnapshot(q, (querySnapshot) => {
querySnapshot.forEach((doc) => {
postItem.push({ ...doc.data(), id: doc.id });
});
});
},
[]);
I wanted to read data from firebase and set my useState with an empty array and even after the data is in the array, the screen still renders an empty array, I need to manually refresh the screen to see the change.
You shouldn’t be pushing directly to postItem. You should be using setPostItem. Also I think you need to add postItem to the end of useEffect in the square brackets.
So maybe something like
useEffect(()=> {
const q = query(
collection(firestone, "latestPost"),
where("userId", "==", ID)
);
onSnapshot(q, (querySnapshot) => {
querySnapShot.forEach((doc) => {
setPostItem([...postItem, {...doc.data(), id:doc.id}])
});
});
}, [postItem]);
Basically that means useEffect will run again once you've setPostItem and also because useState has changed it will refresh the page.
I think that was how it is designed. However someone please correct me if my logic is incorrect!
The only way that react knows that it needs to render again is if you setState. Mutating the existing array will not cause a rerender. Also, don't forget to return the unsubscribe function so your snapshot listener can be torn down when the component unmounts:
useEffect(() => {
const q = query(
collection(firestone, "latestPost"),
where("userId", "==", ID)
);
const unsubscribe = onSnapshot(q, (querySnapshot) => {
const newItems = querySnapshot.docs.map(doc => ({
...doc.data(),
id: doc.id
});
setpostItem(newItems);
});
return unsubscribe;
}, []);