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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:50:34