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

React中更新对象嵌套数组为何不触发子组件重新渲染?

问题原因及解决方案

你的问题核心在于子组件ItemCard用useState存储了props.item,但useState的初始值仅在组件首次挂载时生效。当父组件更新itemsList并传递新的item给子组件时,子组件内部的state不会自动同步props的变化,导致表格无法触发重新渲染。

方案1:直接使用props(推荐,无需子组件维护独立状态)

如果子组件不需要自行修改item数据,完全可以移除子组件内部的state,直接使用传入的props:

// 修改后的ItemCard子组件
const ItemCard = (props) => {
  return (
    <div>
      {props.item.rows.map((row) => (
        // 注意给每一行添加唯一key,帮助React追踪元素变化
        <div key={row.id}>{/* 表格行内容 */}</div>
      ))}
    </div>
  );
}

方案2:子组件需维护独立状态时,用useEffect同步props

如果业务需求必须让子组件自行维护item的状态,需要添加useEffect监听props.item的变化,当props更新时同步到子组件的state中:

import { useState, useEffect } from 'react';

const ItemCard = (props) => {
  const [item, setItem] = useState(props.item);

  // 监听props.item的变化,同步更新子组件state
  useEffect(() => {
    setItem(props.item);
  }, [props.item]); // 依赖项设为props.item,仅当它变化时触发

  return (
    <div>
      {item.rows.map((row) => (
        <div key={row.id}>{/* 表格行内容 */}</div>
      ))}
    </div>
  );
}

额外优化建议

  • 父组件的addRowToItem建议使用函数式更新,避免闭包导致的旧状态问题:
const addRowToItem = (row, itemId) => {
  setItemsList(prevItems => prevItems.map((item) => {
    if (item.id === itemId) {
      return {...item, rows: [...item.rows, row]}; // 展开语法和concat效果一致,写法更灵活
    }
    return item;
  }));
}
  • 所有列表渲染(父组件的itemsList、子组件的rows)都要添加唯一的key属性,这是React列表渲染的最佳实践,能提升渲染性能并避免不必要的bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 13:52:15