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
相关产品推荐
相关产品推荐

