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;
错误截图


问题根源
这是React异步渲染+初始状态为空数组导致的:
- 组件初始化时,
conversations的初始值是空数组[],此时conversations[0]就是undefined,直接访问.name必然报错。 - 控制台“对象变为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
相关产品推荐
相关产品推荐

