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 itself45 // Getting the data from the snapshot and mapping it to an array6 const postList = snapshot.docs.map((doc) => {7 return { id: doc.id, ...doc.data() }8 })910 return (11 <div>12 {/* rendereing the posts */}13 <PostList postList={postList} />14 </div>15 )16}
Explanation:
- We are getting the reference to the collection
posts
from the firestore database. - 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. - Then we are mapping the
snapshot.docs
to an array of objects. We get the data from each document usingdoc.data()
and the id of the document usingdoc.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 cache2export const dynamic = 'force-dynamic'34const Home = () => {5 const collectionRef = collection(db, 'posts')6 const snapshot = await getDocs(collectionRef) // Getting the snapshot not the data itself78 // Getting the data from the snapshot and mapping it to an array9 const postList = snapshot.docs.map((doc) => {10 return { id: doc.id, ...doc.data() }11 })1213 return (14 <div>15 {/* rendereing the posts */}16 <PostList postList={postList} />17 </div>18 )19}
Client component
1const Home = () => {2 const [postList, setPostList] = useState([])34 useEffect(() => {5 ;(async () => {6 const postCollectionRef = collection(db, 'posts')78 const postCollectionSnapshot = await getDocs(postCollectionRef)910 const list = postCollectionSnapshot.docs.map(doc => {11 return { id: doc.id, ...doc.data() }12 })1314 setPostList(list)15 })()16 }, [])1718 return (19 <div>20 {/* rendereing the posts */}21 <PostList postList={postList} />22 </div>23 )24}
Explanation:
- We are using the exact same logic but inside a
useEffect
hook. - 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 = null2let id = 'your-document-id'34const docRef = doc(db, 'posts', id)5const docSnap = await getDoc(docRef)67if (docSnap.exists()) {8 post = { id: docSnap.id, ...docSnap.data() }9}1011if (!post) return // Handle the case when the document is not found
Explanation:
- Again the logic is same. Just use
getDoc
function instead ofgetDocs
- 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
- Email: thatanjan@gmail.com
- LinkedIn: @thatanjan
- Portfolio: anjan
- Github: @thatanjan
- Instagram : @thatanjan
- Twitter: @thatanjan
Blogs you might want to read:
- Eslint, prettier setup with TypeScript and react
- What is Client-Side Rendering?
- What is Server Side Rendering?
- Everything you need to know about tree data structure
- 13 reasons why you should use Nextjs
- Beginners guide to quantum computers
Videos might you might want to watch: