React中Axios请求MongoDB数据时出现Uncaught TypeError问题
问题描述
从MongoDB存储的集合中获取数据时,在Insomnia工具中请求完全正常,但在React项目中使用自定义useFetch Hook + Axios发起请求时,出现错误:Uncaught TypeError: Cannot read properties of undefined (reading 'games')。具体表现为:直接访问data[0]时能在控制台正常打印数据,但访问data[0].games这类嵌套属性就触发报错。
相关代码
自定义useFetch Hook代码
import { useState, useEffect } from 'react'; import axios from 'axios'; const useFetch = (url) => { const [data, setData] = useState(); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { const res = await axios.get(url); setData(res.data); } catch (err) { setError(err); } finally { setLoading(false); } }; fetchData(); }, [url]); return { data, loading, error }; }; export default useFetch;
MongoDB数据模型Schema代码
const mongoose = require('mongoose'); const gameCollectionSchema = new mongoose.Schema({ games: [ { name: String, genre: String, releaseDate: Date } ] }); module.exports = mongoose.model('GameCollection', gameCollectionSchema);
调用Hook的React组件代码
import useFetch from './useFetch'; const GameList = () => { const { data, loading, error } = useFetch('/api/game-collection'); if (loading) return <div>加载中...</div>; if (error) return <div>请求出错:{error.message}</div>; console.log(data[0]); // 正常打印数据 console.log(data[0].games); // 触发TypeError return ( <div> {data[0].games.map(game => ( <div key={game._id}>{game.name}</div> ))} </div> ); }; export default GameList;
问题原因
核心问题是组件渲染时机与数据加载不同步:
- 组件第一次渲染时,
useFetch中的data初始值为undefined,此时data[0]是undefined,直接访问data[0].games就会触发“读取undefined属性”的错误。 - 而直接打印
data[0]时,控制台会保留后续数据加载完成后的更新值,导致你误以为第一次渲染时data[0]就有数据,但实际上报错已经在第一次渲染时发生了。
解决方案
1. 使用可选链操作符(最简便)
在访问嵌套属性时添加?.,自动处理空值情况:
// 安全访问嵌套属性 console.log(data[0]?.games); // 渲染时也可以用 return ( <div> {data[0]?.games?.map(game => ( <div key={game._id}>{game.name}</div> ))} </div> );
2. 强化条件判断
确保数据完全加载后再访问嵌套属性:
const GameList = () => { const { data, loading, error } = useFetch('/api/game-collection'); if (loading) return <div>加载中...</div>; if (error) return <div>请求出错:{error.message}</div>; // 额外判断data是否存在且有数据 if (!data || data.length === 0) return <div>暂无数据</div>; // 此时可以安全访问data[0].games return ( <div> {data[0].games.map(game => ( <div key={game._id}>{game.name}</div> ))} </div> ); };
3. 修正useFetch的初始状态
将data的初始值设为空数组,避免初始时data为undefined:
// 在useFetch Hook中修改初始state const [data, setData] = useState([]);
内容的提问来源于stack exchange,提问作者encoded
相关产品推荐
相关产品推荐

