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

React Hooks中fetch获取的克隆对象嵌套数组无法调用map()问题

问题修复方案

1. Cannot read property 'map' of undefined 报错根因与修复

你只做了copyRecipe存在的判断,但初始状态下copyRecipe是空对象,不存在ingredients字段,该字段值为undefined,调用map方法自然触发报错。而食用份量数值能正常显示是因为JSX渲染undefined时只会不显示内容,不会抛出语法级错误。
修复方法:在调用map前增加ingredients存在性判断,推荐使用ES2020可选链运算符简化写法:

// 修改前
{copyRecipe.ingredients.map((item,index) => {})}
// 修改后
{copyRecipe.ingredients?.map((item,index) => {})}

如果需要兼容低版本JS环境,也可以用逻辑与判断:

{copyRecipe.ingredients && copyRecipe.ingredients.map((item,index) => {})}

2. console.log打印多次空值的根因

  • 子组件首次渲染:copyRecipe初始值为空对象,第一次打印{}
  • 父组件useFetch加载数据前,传入的recipe为undefined,触发useEffect执行setCopyRecipe({...undefined}),本质还是赋值空对象,触发第二次渲染打印{}
  • React 18及以上版本默认开启严格模式,开发环境下会刻意重复执行一次组件渲染与副作用逻辑,因此上述两次渲染会翻倍,得到4次空值打印
  • 等useFetch拿到真实数据后,传入的recipe更新,触发第五次渲染,打印出有值的对象

3. 额外代码优化建议

你当前写的全局duplicate变量每次组件渲染都会生成一次,属于无用操作,修改状态时直接在setCopyRecipe的回调里做浅拷贝即可,避免潜在的状态不一致问题,优化后的完整子组件代码如下:

const Child = ({recipe}) =>{
  // 初始值直接用传入的recipe,避免多余的空对象赋值
  const [copyRecipe, setCopyRecipe] = useState(recipe);
   
  useEffect(() => {
    // 仅当recipe有值时才更新状态,避免无效赋值
    if(recipe) {
      setCopyRecipe({...recipe});
    }
  }, [recipe]);
   
  const incrementHandle = () => {
    // 用状态回调拿到最新值,避免闭包问题
    setCopyRecipe(prevState => {
      const newState = {...prevState};
      newState.servings = `${parseInt(newState.servings) + 1}`;
      return newState;
    });
  };

  console.log(copyRecipe);

  return(
    <>
      {copyRecipe?.servings && <p>{copyRecipe.servings}</p>}
      <Increment onClick={incrementHandle}/>
      {copyRecipe?.ingredients?.map((item,index) => {
        // 执行相关逻辑
      })}
    </>
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 10:15:05