Home > Enterprise >  How can I update state of an array every time a new category is added?
How can I update state of an array every time a new category is added?

Time:12-23

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()
}, []);

  • Related