How to get documents from Firebase Firestore in Nextjs14

In this blog, we will learn how to get documents from Firebase Firestore in Nextjs14. We will learn:

  • How to get a collection of documents using both server and client components.
  • How to revalidate the data in server components.
  • How to get a single document.

Video Tutorial

I have created a video tutorial which is a part of my Next.js 14 Firestore series on YouTube. You can watch the video tutorial for a better understanding of the topic.

{% youtube chwX8tW37tI %}

Server component

1const Home = () => {
2 const collectionRef = collection(db, 'posts')
3 const snapshot = await getDocs(collectionRef) // Getting the snapshot not the data itself
4
5 // Getting the data from the snapshot and mapping it to an array
6 const postList = snapshot.docs.map((doc) => {
7 return { id: doc.id, ...doc.data() }
8 })
9
10 return (
11 <div>
12 {/* rendereing the posts */}
13 <PostList postList={postList} />
14 </div>
15 )
16}

Explanation:

  1. We are getting the reference to the collection posts from the firestore database.
  2. Then passing the reference to the getDocs function to get the snapshot of the collection. Snapshot is not the data itself, it's the metadata of the collection.
  3. Then we are mapping the snapshot.docs to an array of objects. We get the data from each document using doc.data() and the id of the document using doc.id.

Server component revalidation

Server components are cached by default. Which means the data will not be fetched during build time and the page will be built with that data. So, if you change your data from console, you won't see any changes after page is built. You won't notice the changes on locally however you can test this by building your code with npm run build. You need to revalidate to see the changes. You can:

  • Revalidate after a certain amout of time like 1 hour, 1 day etc.
  • Refetch the data on every request.
  • Redeploy the app.

We will revalidate the data on every request by exoprting a variable dynamic from the component.

1// Avoiding cache
2export const dynamic = 'force-dynamic'
3
4const Home = () => {
5 const collectionRef = collection(db, 'posts')
6 const snapshot = await getDocs(collectionRef) // Getting the snapshot not the data itself
7
8 // Getting the data from the snapshot and mapping it to an array
9 const postList = snapshot.docs.map((doc) => {
10 return { id: doc.id, ...doc.data() }
11 })
12
13 return (
14 <div>
15 {/* rendereing the posts */}
16 <PostList postList={postList} />
17 </div>
18 )
19}

Client component

1const Home = () => {
2 const [postList, setPostList] = useState([])
3
4 useEffect(() => {
5 ;(async () => {
6 const postCollectionRef = collection(db, 'posts')
7
8 const postCollectionSnapshot = await getDocs(postCollectionRef)
9
10 const list = postCollectionSnapshot.docs.map(doc => {
11 return { id: doc.id, ...doc.data() }
12 })
13
14 setPostList(list)
15 })()
16 }, [])
17
18 return (
19 <div>
20 {/* rendereing the posts */}
21 <PostList postList={postList} />
22 </div>
23 )
24}

Explanation:

  1. We are using the exact same logic but inside a useEffect hook.
  2. Once the data is fetched, we are setting the data to the state using setPostList.

With client components, you don't need to worry about revalidation as the data is fetched on every request.

Fetching a single document

1let post = null
2let id = 'your-document-id'
3
4const docRef = doc(db, 'posts', id)
5const docSnap = await getDoc(docRef)
6
7if (docSnap.exists()) {
8 post = { id: docSnap.id, ...docSnap.data() }
9}
10
11if (!post) return // Handle the case when the document is not found

Explanation:

  1. Again the logic is same. Just use getDoc function instead of getDocs
  2. You can check if the document exists using docSnap.exists() method.

That's it for this blog. I hope you found it helpful. If you have any questions, feel free to ask in the comments section below.

Shameless Plug

I have made an Xbox landing page clone with React and Styled components. I hope you will enjoy it. Please consider like this video and subscribe to my channel.

That's it for this blog. I have tried to explain things simply. If you get stuck, you can ask me questions.

Contacts

Blogs you might want to read:

Videos might you might want to watch:

Previous PostHow to add documents to firestore from Nextjs14 using Server component and Server action
Next PostHow to add multiple documents to firestore from Nextjs14