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

React.js中map遍历映射项调用异步请求获取分类长度报错如何解决

问题根因
  • 你直接在JSX渲染语法中调用了异步length函数,所有async声明的函数默认返回Promise对象,React不支持直接将Promise作为渲染内容,这就是触发Objects are not valid as a React child报错的核心原因。
  • 其次该写法会导致组件每一次重渲染都重复发起接口请求,存在严重的性能问题和内存泄漏风险。
修复方案

推荐两种常用实现方式,按需选择即可:

方案1:批量请求所有分类长度后统一渲染

在组件内新增state存储所有分类对应的长度,在分类列表更新时批量请求数据后再渲染:

// 新增state存储所有分类长度
const [categoryLengths, setCategoryLengths] = useState({});

useEffect(() => {
  const fetchAllLengths = async () => {
    const lengthMap = {};
    for (const item of categories) {
      // 调用你原有逻辑获取长度
      const len = await length(item.id);
      lengthMap[item.id] = len;
    }
    setCategoryLengths(lengthMap);
  };
  // 仅当分类列表更新时重新请求
  fetchAllLengths();
}, [categories]);

渲染时直接从state中取值即可:

{categories.map((x, index) => {
  return (
    <div key={index} className="col-xl-3 col-lg-3 col-md-3 col-6">
      <div className="dashboard__categories-item">
        <span style={{ color: `${x.color}` }}>{x.icon}</span>
        <h5>{x.title}</h5>
        {/* 未加载完成时显示兜底文案 */}
        <h5>Length: {categoryLengths[x.id] ?? '加载中'}</h5>
      </div>
    </div>
  );
})}

方案2:拆分独立子组件单独管理请求

把每个分类项拆成独立子组件,每个组件内部管理自己的长度请求逻辑,更适合分类数量多的场景:

// 独立分类项组件
const CategoryItem = ({ category }) => {
  const [len, setLen] = useState(0);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchLen = async () => {
      const res = await length(category.id);
      setLen(res);
      setLoading(false);
    };
    fetchLen();
  }, [category.id]);

  return (
    <div className="col-xl-3 col-lg-3 col-md-3 col-6">
      <div className="dashboard__categories-item">
        <span style={{ color: category.color }}>{category.icon}</span>
        <h5>{category.title}</h5>
        <h5>Length: {loading ? '加载中' : len}</h5>
      </div>
    </div>
  );
};

// 原父组件内直接使用子组件
{categories.map((x, index) => <CategoryItem key={index} category={x} />)}
额外优化建议

可以给你的请求函数增加错误兜底逻辑,避免接口请求失败导致页面异常:

async function getLength(category_id) {
  try {
    const res = await axios.post("/api/passwords/categories", {
      category_id,
      user_id,
    });
    return res;
  } catch (err) {
    console.error(err);
    // 接口报错时返回兜底值
    return { data: { length: 0 } };
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 17:15:07