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

React中Uncaught TypeError: projects.map不是函数问题排查

问题解决:React组件首次渲染时projects.map报错

问题根源

你的代码核心问题是初始state类型错误:

const [projects, setProjects] = useState('');

首次渲染时projects是空字符串(而非数组),字符串并没有map方法,直接调用projects.map就会抛出Uncaught TypeError: projects.map is not a function错误。同时Array.isArray(projects)返回false,所以Array.isArray(projects)&&projects.length结果也为false。

等到useEffect里的异步请求完成后,setProjects把projects更新为数组,第二次渲染时就能正常执行map逻辑了。

修复方案

1. 修正初始state为数组

把初始值从空字符串改成空数组,这样首次渲染时projects是数组类型,即便为空也能安全调用map:

const [projects, setProjects] = useState([]);

2. (可选)添加加载状态优化体验

如果数据加载耗时较长,可添加加载状态避免页面空白:

const [projects, setProjects] = useState([]);
const [isLoading, setIsLoading] = useState(true); // 新增加载状态

useEffect(()=>{
    const getProjects = async () => {
        const data = await getDocs(projectRef)
        setProjects(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })))
        setIsLoading(false); // 数据加载完成后关闭加载状态
    }
    getProjects()
},[]);

// 渲染时先判断加载状态
if (isLoading) {
    return <div>加载中...</div>;
}

3. (可选)添加类型检查(双重保障)

如果担心projects被意外修改为非数组类型,可在调用map前做类型校验:

const projec = Array.isArray(projects) ? projects.map(proj => {
    // 原map逻辑
}) : [];

完整修复后的代码

import  { useEffect, useState } from 'react';
import {useDispatch } from 'react-redux';
import { deleteProject } from '../../store/projectSlice';
import {  db } from '../../config/firebaseConfig';
import { getDocs , collection } from 'firebase/firestore';

const ProjectSummary = () => {
    // 修正初始state为数组
    const [projects, setProjects] = useState([]);
    const [isLoading, setIsLoading] = useState(true);
    const projectRef = collection(db, 'projects')
    const dispatch = useDispatch();

    useEffect(()=>{
        const getProjects = async () => {
            const data = await getDocs(projectRef)
            setProjects(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })))
            setIsLoading(false);
        }
        getProjects()
    },[]);

    const handleDelete = (id) => {
        dispatch(deleteProject(id))
    }

    if (isLoading) {
        return <div>加载中...</div>;
    }

    const projec = projects.map(proj => {
        return (
            <div className="card z-depth-o project-summary" key={proj.id}>
                <div className="card-content grey-text text-darken-3" >
                    <span className="card-title"> {proj.title}</span>
                    <p>{proj.content}</p>
                    <p className="grey-text">less than a minute ago</p>
                    <button
                        onClick={() => handleDelete(proj.id)}
                        >Delete Project
                    </button>
                </div>
            </div>
        )
    })

    return (
        <div>{ projec}</div>
    )
}

export default ProjectSummary

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 05:53:19