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

React前端Uncaught TypeError:无法读取undefined的'name'属性

React获取数组后访问属性报错:Cannot read properties of undefined (reading 'name')

问题描述

从后端获取对象数组后,访问对象属性时触发Uncaught TypeError: Cannot read properties of undefined (reading 'name')错误。不访问属性时控制台能正常打印对象,但一旦尝试访问属性,控制台里的对象也会显示为undefined。

相关代码

自定义Hook useGetConversations

import { useEffect, useState } from "react";
import toast from "react-hot-toast";

const useGetConversations = () => {
    const [loading, setLoading] = useState(false);
    const [conversations, setConversations] = useState([]);

    useEffect(() => {
        const getConversations = async () => {
            setLoading(true);
            try {
                const res = await fetch("/api/users");
                const data = await res.json();
                if (data.error) {
                    throw new Error(data.error);
                }
                
                setConversations(data);
                
            } catch (error) {
                toast.error(error.message);
            } finally {
                setLoading(false);
            }
        };

        getConversations();
    }, []);
    console.log("before return statement",conversations[0]);// 仅当不访问属性时能正常运行
    console.log("before return statement",conversations[0].name);
    return { loading, conversations };
};
export default useGetConversations;

业务组件 Conversations

import useGetConversations from "../../hooks/useGetConversations";
import { getRandomEmoji } from "../../utils/emojis";
import Conversation from "./Conversation";

const Conversations = () => {
    const { loading, conversations } = useGetConversations();

    // 能成功打印对象数组
    // console.log(conversations);
    // 能成功打印单个对象
    // console.log(conversations[0]); 
    // 无法打印对象属性,且之前的打印内容也变为undefined
    // console.log(conversations[0].name); 
    return (
        <div className='py-2 flex flex-col overflow-auto'>
            {conversations.map((conversation, idx) => (
                <Conversation
                    key={conversation._id}
                    conversation={conversation}
                    emoji={getRandomEmoji()}
                    lastIdx={idx === conversations.length - 1}
                />
            ))}

            {loading ? <span className='loading loading-spinner mx-auto'></span> : null}
        </div>
    );
};
export default Conversations;

错误截图

错误截图1
错误截图2

问题根源

这是React异步渲染+初始状态为空数组导致的:

  1. 组件初始化时,conversations的初始值是空数组[],此时conversations[0]就是undefined,直接访问.name必然报错。
  2. 控制台“对象变为undefined”是浏览器特性:控制台打印的是引用,当组件报错后,浏览器会更新显示为undefined,但本质是第一次渲染时conversations[0]确实不存在。

解决方法

方法1:用可选链操作符做安全访问

在访问属性前添加?.,只有当左侧值不为undefined/null时才会访问右侧属性,否则直接返回undefined,避免报错:

// 在hook中修改打印逻辑
console.log("before return statement", conversations[0]?.name);

// 在组件中单独访问属性时
console.log(conversations[0]?.name);

方法2:结合loading状态做条件判断

利用已有的loading状态,在数据加载完成前不执行属性访问逻辑:

// 在hook中
if (!loading && conversations.length > 0) {
  console.log("before return statement", conversations[0].name);
}

// 在组件中如果要单独渲染第一个元素的属性
{!loading && conversations[0] && <div>{conversations[0].name}</div>}

方法3:调整初始状态(可选)

把conversations的初始状态设为null,明确区分“未加载”和“加载完成但空数组”的状态:

// hook中修改初始状态
const [conversations, setConversations] = useState(null);

// 组件中做状态判断
if (loading) return <span className='loading loading-spinner mx-auto'></span>;
if (!conversations) return null;
return (
  <div className='py-2 flex flex-col overflow-auto'>
    {conversations.map(...)}
  </div>
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 07:07:52