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

React调用API时报错Cannot read properties of undefined (reading 'map')求解

问题原因

两次打印、首次输出为空的原因

  • 首次打印是组件第一次渲染时触发,此时useEffect内的异步请求还未返回结果,items还是你设置的初始值。
  • 第二次打印是异步请求拿到返回结果后,调用setItems触发组件重新渲染,此时items已经是接口返回的完整数据。
  • 如果你使用的是React18+的开发环境,并且项目开启了严格模式(React.StrictMode),useEffect会默认执行两次,这是开发环境的正常特性,生产环境会自动恢复为单次执行。

报错的根源

你给items设置的初始值是空数组[],数组本身不存在dataseries属性,虽然你写了isLoaded的加载判断,但由于你请求成功后先修改了isLoaded为true、再给items赋值,或者接口返回异常的情况下,很容易出现items.dataseries为undefined的情况,调用undefined.map自然就抛出了类型错误。另外你原代码中map的回调只有console.log,没有返回合法的JSX元素,也会导致渲染报错。

解决方案
  1. 修正初始值和状态更新顺序,items是接口返回的对象,初始值设置为空对象更合理,同时先更新数据再修改加载状态,避免加载状态结束但数据还未赋值的情况:
// 把初始值从空数组改为空对象
const [items, setItems] = useState({});

// 请求成功的回调调整更新顺序
(result) => {
  setItems(result); 
  setIsLoaded(true);
}
  1. 渲染时添加非空判断,使用可选链运算符避免访问不存在的属性,同时补全map返回的列表元素和key属性:
return (
  <ul>
    {items?.dataseries?.map(item => (
      <li key={item.date}>
        {console.log(item)}
        {/* 这里补充你要渲染的内容 */}
        {JSON.stringify(item)}
      </li>
    ))}
  </ul>
);
  1. 如果需要解决严格模式下重复请求的问题,可以在useEffect中添加请求取消逻辑:
useEffect(() => {
  const controller = new AbortController();
  fetch("http://www.7timer.info/bin/api.pl?lon=113.17&lat=23.09&product=astro&output=json", {
    signal: controller.signal
  })
  .then(res => res.json())
  .then(
    (result) => {
      setItems(result); 
      setIsLoaded(true);
    },
    (error) => {
      // 忽略取消请求的报错
      if (error.name !== 'AbortError') {
        setIsLoaded(true);
        setError(error);
      }
    }
  )
  // 组件卸载时取消未完成的请求
  return () => controller.abort();
}, [])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 13:39:03