'Can't update DOM by using useEffect and Firebase/Firestore

I got stuck on updating DOM, using useEffect and sending-getting data from Firebase. I work on a basic photo gallery website, that user selects a picture on local and send it Firebase/Firestore. All firebase actions work well. The main problem when I select image, it sends image immediately, but page doesn't update. When I manually update, then all images show up.

This is app.js file;

<div className='main'>
     <Title />
     <UploadForm />
     <ImageGallery />
</div>

I upload image with UploadForm component then want to update DOM and add image to DOM immediately. Here is my cumtom hook (useFirestore.js) file;

import { useState, useEffect } from 'react';
import { projectFirestore } from '../firebase/config';
import { query, orderBy, getDocs, collection } from 'firebase/firestore';

const useFirestore = (collectionName) => {
  const [docs, setDocs] = useState([]);

  useEffect(() => {
    const getDocuments = async (collectionName) => {
      const queryIt = query(
        collection(projectFirestore, collectionName),
        orderBy('createdAt', 'desc')
      );

      const querySnapshot = await getDocs(queryIt);
      let documents = [];
      querySnapshot.forEach((doc) => {
        documents.push({ ...doc.data(), id: doc.id });
      });
      setDocs(documents);
    };

    getDocuments(collectionName);
  }, [collectionName]);

  return { docs };
};

export default useFirestore;

This docs object return to ImageGallery.js file which is:

const ImageGallery = () => {
  const { docs } = useFirestore('images');
  console.log('docs: ', docs);

  return (
    <div className={classes.gallery}>
      {docs &&
        docs.map((doc) => {
          return (
            <Card key={doc.id}>
              <img src={doc.url} alt='Wallpaper Pictures' />
            </Card>
          );
        })}
    </div>
  );
};

export default ImageGallery;

I tried many possibilities but I failed.



Solution 1:[1]

It might be because you are using getDocs instead of onSnapshot inside of your useFirestore hook.

You can read more about it in the Firebase documentation.

Solution 2:[2]

I post this message to help who struggle with the same problem. The real problem was using getDocs instead of onSnapshot as @Sandrow said. The code snippet that solve my problem is:

  useEffect(() => {
        const q = query(
      collection(projectFirestore, collectionName),
      orderBy('createdAt', 'desc')
    );
    const unsubscribe = onSnapshot(q, (querySnapshot) => {
      const documents = [];
      querySnapshot.forEach((doc) => {
        documents.push({ ...doc.data(), id: doc.id });
      });
      setDocs(documents);
    });

    return () => unsubscribe();
  }, [collectionName]);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sandrow
Solution 2 mithderler