Here i am trying to display all the data to my post page from my firebase, but instead i am getting this type of error:
TypeError: Cannot read properties of undefined (reading ‘map’)
Here is my Feed.js where does the work for getting all the data from the firebase.
import { SparklesIcon } from '@heroicons/react/outline'
import React, { useEffect, useState } from 'react'
import Input from './Input'
import Post from './Post'
import { collection, onSnapshot, orderBy, query } from 'firebase/firestore';
import { db } from '@/firebase';
export default function Feed() {
const [posts, setPosts] = useState();
useEffect(
() =>
onSnapshot(
query(collection(db, "posts"), orderBy("timestamp", "desc")),
(snapshot) => {
setPosts(snapshot.docs);
}
),
[]
);
return (
<div className="xl:ml-[370px] border-1 border-r border-l border-r-gray-200 xl:min-w-[576px] sm:ml-[73px] flex-grow max-x-xl">
{/* Home nav */}
<div className="flex items-center py-3 px-3 sticky top-0 z-50 bg-white border-b border-gray-200">
<h2 className="text-lg sm:text-xl font-bold cursor-pointer">Home</h2>
<div className="hoverEffect flex items-center justify-center px-0 ml-auto w-9 h-9">
<SparklesIcon className="h-5" />
</div>
</div>
{/* Input */}
<Input />
{/* Post */}
{posts.map((post) => (
<Post key={post.id} posts={post} />
))}
</div>
)
}
And, I want the all data to display into Post.js
Here is the code for Post.js
import { ChartBarIcon, ChatIcon, DotsHorizontalIcon, HeartIcon, ShareIcon, TrashIcon } from '@heroicons/react/outline'
import Image from 'next/image'
import React from 'react'
export default function Post({ post }) {
return (
<div className="flex p-3 cursor-pointer border-b border-gray-200">
{/* user-img */}
<Image
src={post.userImg}
alt="img-user"
className="w-11 h-11 rounded-full mr-4 object-cover"
width="50"
height="50"
>
</Image>
{/* right-side */}
<div>
{/* header */}
<div className="flex items-center justify-between">
{/* post-user-info */}
<div className="flex items-center justify-between space-x-2">
<h4 className="font-bold text-[15px] sm:text-[16px] hover:underline">{post?.name}</h4>
<span className="text-sm sm:text-[15px] text-gray-500">@{post?.username} •</span>
<span className="text-sm sm:text-[15px] text-gray-500 hover:underline">{post?.timestamp}</span>
</div>
{/* dot-icon */}
<DotsHorizontalIcon className="h-10 hoverEffect w-10 hover:bg-sky-100 hover:text-sky-500 p-2" />
</div>
{/* post-text */}
<p className="text-gray-800 text[15px sm:text-[16px] mb-2">{post?.text}</p>
{/* post-img */}
<Image
src={post?.image}
width="500"
height="500"
alt="post-img"
className="rounded-2xl mr-2 w-auto"
>
</Image>
{/* icons */}
<div className="flex justify-between text-gray-500 p-2">
<ChatIcon className="h-9 w-9 hoverEffect p-2 hover:bg-sky-100 hover:text-sky-500"/>
<TrashIcon className="h-9 w-9 hoverEffect p-2 hover:bg-red-100 hover:text-red-500"/>
<HeartIcon className="h-9 w-9 hoverEffect p-2 hover:bg-red-100 hover:text-red-500"/>
<ShareIcon className="h-9 w-9 hoverEffect p-2 hover:bg-green-100 hover:text-green-500"/>
<ChartBarIcon className="h-9 w-9 hoverEffect p-2 hover:bg-sky-100 hover:text-sky-500"/>
</div>
</div>
</div>
)
}
2
Answers
You’re initializing
posts
like this:Since you’re not passing any value to
useState
, the initial value ofposts
isundefined
. And since you then use this as{posts.map((post) => (
in the rendering code, you get the error message.The solution is to initialize
posts
with a value that your code can handle, like:Now
posts
will initially be an empty array, which means you render an empty list instead of getting an error.You’re getting this error because you aren’t passing an
initial state value
into your call touseState
. WhenFeed
first renders, it tries to callmap
against thepost
state variable which isundefined
until the useEffect can run youronSnapshot
which updates posts to (hopefully) be an array.To fix this, update your call to
useState
by passing an empty array as the initial state value:Also, I don’t know if
snapshot.docs
can come back asundefined|null
but it never hurts to be sure that the posts value is always an array.Consider adding a nullish coalescing operator (??) to your call to
setPosts
like so:I’ve updated your code snippet to reflect these changes.
Hope this helps!