Trying to build my first project using React and firebase. I have a Header.jsx
component where I'm mapping names of all added categories like shown below:
const [data, setData] = useState([]);
// Getting all categories from firebase.
useEffect(() => {
const fetchData = async () => {
let list = []
try{
const categories = collection(db, 'category')
let mquery = query(categories, orderBy('timeStamp', "desc"))
const querySnapshot = await getDocs(mquery);
querySnapshot.forEach((doc) => {
list.push({ id: doc.id, ...doc.data()});
});
setData(list);
} catch (err) {
console.log(err)
}
};
fetchData()
}, []);
// Mapping category names in the header
<ul className="absolute hidden text-white pt-1 group-hover:block items-center">
{data.map((category, index) => {
return (
<Link to={`/categories/${category.name}`} key={category.id}>
<li className='rounded-lg p-2 hover:text-white/80 hover:-translate-y-1 hover:scale-110 duration-300 transition ease-in-out delay-150'>
<span>{category.name}</span>
<li>
</Link>
)
})}
When I'm adding a new category, the new category name is not displayed, it's only displayed if I refresh the page.
I suppose that this is due to not updating the state, [data], right? How can I update the state and add a new category name without refreshing?
CodePudding user response:
I've managed to solve it by implementing an onSnapshot
listener. You can check firebase docs https://firebase.google.com/docs/firestore/query-data/listen#listen_to_multiple_documents_in_a_collection.
Also helpful link useEffect rendering multiple times even when data is not changing
useEffect(() => {
const categories = collection(db, 'category')
let mquery = query(categories, orderBy('timeStamp', "desc"))
const unsubscribe = onSnapshot((mquery), (querySnapshot) => {
const list = [];
querySnapshot.forEach((doc) => {
list.push({ id: doc.id, ...doc.data()});
});
setData(list);
});
}, []);
CodePudding user response:
Try this instead.
// Getting all categories from firebase.
useEffect(() => {
const fetchData = async() => {
try {
const categories = collection(db, 'category')
let mquery = query(categories, orderBy('timeStamp', "desc"))
const querySnapshot = await getDocs(mquery);
const list = querySnapshot.docs.map((doc) => {
return {
id: doc.id,
...doc.data()
};
});
setData(list);
} catch (err) {
console.log(err)
}
};
fetchData()
}, []);