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

React使用axios+useEffect请求REST API时空数组导致map报错

问题原因

你观察到的两次控制台输出、首次渲染拿到空数组都是React的正常运行逻辑,不是bug:

  • 组件首次挂载时,useState初始化的data为空数组,此时异步接口请求尚未返回,会触发第一次渲染
  • 接口请求完成后调用setData更新状态,触发组件重渲染,此时data才是接口返回的真实业务数据,控制台会打印第二次结果
    不存在数据重复问题,异步状态下的多次渲染是React的固有机制。你遇到的map方法报错,本质是未等数据就绪就执行数组遍历,甚至可能是接口返回非数组类型值覆盖了初始空数组导致的。
    控制台两次输出日志截图
解决方案

你在自定义Hook中已经定义了loading状态,直接用这个状态做渲染拦截是成本最低、逻辑最清晰的方案。

方案1:基于loading状态做条件渲染(推荐)

加载阶段先展示占位提示,等数据请求完成后再渲染列表内容,从根源上避免未就绪状态下的方法调用报错。
修改customsite.jsx代码如下:

import React from 'react';
import Modal from './reusable/modal';
import useFetchData from './hooks/useFetchData';

const Customsite = ()=> {
  const {
    data,
    loading,
  } = useFetchData();

  // 加载中直接返回占位内容,不执行后续列表渲染逻辑
  if (loading) return <div>数据加载中,请稍候...</div>

  return(
    <div>
     <p>站点列表</p>
     {/* 到这里时loading已经为false,data已更新为接口返回的真实数据 */}
     <ul>
      {data.map(item => <li key={item.id}>{item.siteName}</li>)}
     </ul>
    </div>
  )
}

export default Customsite

方案2:增加类型防御兜底

如果不需要单独的加载态,可以在遍历前加类型判断,哪怕data意外变成非数组值也不会触发报错:

return(
  <div>
   <p> we here </p>
   <ul>
    {/* 仅当data是数组类型时才执行map遍历,否则渲染空 */}
    {Array.isArray(data) && data.map(item => <li key={item.id}>{item.siteName}</li>)}
   </ul>
  </div>
)
自定义Hook优化建议

你当前的useFetchData缺少错误状态,也没有对接口返回值做类型校验,建议补充以下逻辑,进一步降低报错概率:

import { useEffect, useState} from 'react';
import http from '../../services/httpservices';
import config from '../../services/config.json';

const useFetchData = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

 useEffect(() => {
 const fetchData = async () => {
  try {
    const { data: response } = await http.get(config.apiEndpoint);
    // 校验返回值类型,非数组时兜底为空数组,避免后续map报错
    setData(Array.isArray(response) ? response : []);
    setError(null);
  } catch (error) {
    console.error(error)
    setError(error);
    setData([]); // 请求出错时重置data为空数组
  }
   setLoading(false);
  };

   fetchData();
  }, []);
 return {
  data,
  loading,
  error,
 };
};

export default useFetchData;
注意事项
  • 不存在“跳过首次渲染、直接获取真实数据”的实现方式,React函数组件首次渲染是挂载流程的必经环节,所有异步状态都要经过「初始值渲染->异步更新->重渲染」的流程
  • 纯空数组[]调用map不会触发报错,如果你的代码出现相关报错,大概率是接口返回了null/undefined/对象等非数组值,覆盖了初始的空数组,因此类型校验很有必要
  • 开发环境下如果开启了React严格模式,控制台可能出现3次及以上打印,属于正常现象,生产环境不会有该问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 22:09:39