I am having some problems with firebase, I am using firestore onSnapshot to get realtime updates inside an useEffect like this:
useEffect(() => {
const unsubscribe = () => {
firebase
.firestore()
.collection("posts")
.orderBy("createdAt", "desc")
.onSnapshot((post) => {
const data = post.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setPosts(data);
setLoading(false);
});
};
return () => unsubscribe();
}, []);
But it does not work, I do not get the data when the components mounts, the weird fact is that when I use it without returning the unsubscribe function it work perfectly. like this:
useEffect(() => {
firebase
.firestore()
.collection("posts")
.orderBy("createdAt", "desc")
.onSnapshot((post) => {
const data = post.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setPosts(data);
setLoading(false);
});
}, []);
I really would like to know why the first approach is not working, which is the ideal way to do it. I am also using React Router DOM, here you can see my Posts component which renders a Post component when I get the data.
export default function Posts() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
console.log("data listener...");
const unsubscribe = () => {
firebase
.firestore()
.collection("posts")
.orderBy("createdAt", "desc")
.onSnapshot((post) => {
console.log("el console desde posts listeners..");
const data = post.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setPosts(data);
setLoading(false);
});
};
return () => unsubscribe();
}, []);
//Not working
return (
<main className="posts">
{loading && <h3>Loading posts...</h3>}
{posts && posts.map((post) => <Post {...post} key={post.id} />)}
</main>
);
}
This Posts component is being rendered by:
export default function Home() {
return (
<div className="home">
<Nav />
<Posts />
</div>
);
}
That's because your listener is wrapped in side of another function and hence that won't be called unless you invoke the unsubscribe
function.
const unsubscribe = () => { firebase.collection("posts").... }
Try this instead
const unsubscribe = firestore.collection("posts")....
// now calling, unsubscribe() will detach the listenter