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

React递归提取嵌套对象报can't convert undefined to object如何解决?

问题修复方案

你遇到的问题由三个核心原因导致:

  • React 状态更新为异步行为,执行setBakery后立刻打印bakery获取的是更新前的旧值,并非状态未成功写入
  • 页面首次渲染时bakery初始值为空数组,监听bakery的useEffect会先触发一次执行,此时extractNestedData取objects[0]得到undefined,传入Object.values就会触发类型报错
  • 原有递归逻辑存在两个错误:用const声明的data变量被二次赋值,以及递归调用返回的结果没有被收集到最终输出数组中,导致无法提取嵌套数据

以下是修复后的完整可运行代码:

import { useState, useEffect } from 'react';
import axios from 'axios';

// API Call
const fetchData = async () => {
  try {
    const response = await axios.get(
      "https://60d007f67de0b200171079e8.mockapi.io/bakery"
    );
    console.log('fetched data', response.data)
    return response.data;
  } catch (err) {
    console.error(err);
    return [];
  }
};

const extractData = (objects) => {
  const objectKeys = [];
  // 加非空判断,避免处理undefined
  if (!objects || typeof objects !== 'object') return objectKeys;
  
  const values = Object.values(objects)
  values.forEach(val => {
    if (val && typeof val === "object") {
      // 收集递归返回的嵌套值
      objectKeys.push(...extractNestedData(val))
    } else {
      objectKeys.push(val)
    }
  })
  return objectKeys;
}

const extractNestedData = (objects) => {
  // 兼容空入参
  if (!objects || !Array.isArray(objects) || objects.length === 0) return [];
  const object = objects[0];
  // 把const改为let,允许重新赋值
  let data = []
  data = extractData(object)
  return data;
}

export default function App() {
  const [bakery, setBakery] = useState([])
  const [flatBakery, setFlatBakery] = useState([])

  useEffect(() => {
    let mount1 = true;
    if(mount1){
      fetchData().then((randomData) => {
        setBakery(randomData)
        // 这里打印的是旧值,属于正常现象
        console.log('set后立刻打印的bakery(旧值)', bakery)
      })
    }
    return () => { mount1 = false;}
  }, []);
  
  useEffect(() => {
    let mount2 = true;
    if (mount2 && bakery.length > 0) {
      // 只有bakery有值时才执行提取逻辑
      setFlatBakery(extractNestedData(bakery));
      // 这里可以拿到更新后的bakery值
      console.log('更新后的bakery', bakery)
    }
    return () => mount2 = false;
  }, [bakery])

  // 可以在这里打印flatBakery验证提取结果
  console.log('扁平化后的数据', flatBakery)
  
  return (
    <div>
      Hello
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 19:36:10