You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Firebase获取数据渲染时出现TypeError: Cannot read properties of undefined (reading 'map')

解决TypeError: Cannot read properties of undefined (reading 'map')及Firebase数据展示问题

错误原因分析

  1. 初始状态未初始化数组:posts初始值为undefined,组件首次渲染时执行posts.map()会直接报错,因为undefined没有map方法。
  2. Firestore文档数据未提取:snapshot.docs返回的是Firestore文档对象集合,不是直接的帖子数据,需要调用.data()提取文档内容,同时保留文档ID。
  3. Props传递不匹配:Feed组件给Post传递的props是posts={post},但Post组件接收的是post,导致Post内部无法正确获取数据。
  4. 可选链使用不完整:Post组件中部分属性(如post.userImg)未使用可选链,若数据加载延迟或缺失会引发报错。
  5. CSS语法错误:Post组件中post-text的class存在语法错误,导致样式失效。

修复代码

1. 修改Feed.js

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() {
    // 初始化为空数组,避免首次渲染map报错
    const [posts, setPosts] = useState([]);
    useEffect(
        () => 
            onSnapshot(
                query(collection(db, "posts"), orderBy("timestamp", "desc")), 
                (snapshot) => {
                    // 提取文档数据并带上id
                    const postsData = snapshot.docs.map(doc => ({
                        id: doc.id,
                        ...doc.data()
                    }));
                    setPosts(postsData);
                }
            ),
        []
    );
  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 */}
        {/* 修正props键名,传递post给Post组件 */}
        {posts.map((post) => (
            <Post key={post.id} post={post} />
        ))}
    </div>
  )
}

2. 修改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"
        />

        {/* 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} &#8226;</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 - 修复class语法错误 */}
            <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"
            />

            {/* 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>
  )
}

关键修复点说明

  • 初始化posts为空数组[],确保首次渲染时map能正常执行(空数组的map不会报错)。
  • 处理Firestore快照时,通过doc.data()提取实际数据,并合并文档ID到数据对象中,方便后续使用。
  • 修正Feed组件中Post的props传递,将posts={post}改为post={post},与Post组件的接收参数匹配。
  • 给Post组件中所有访问post属性的地方添加可选链?.,防止数据未加载完成时出现属性访问错误。
  • 修复Post组件中post-text的class语法错误(原代码text[15px sm:text-[16px]缺少闭合方括号)。

内容的提问来源于stack exchange,提问作者Levi Ackerman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 14:50:54