为什么更新对象中的嵌套数组不会触发子组件重新渲染?

Why updating a nested array in an object doesn't trigger child component re-render?

提问人:Herman Shpryhau 提问时间:10/6/2023 更新时间:10/6/2023 访问量:61

问:

在我的 React 应用程序中,我有一个页面,它由项目卡片列表(每个卡片都是一个单独的组件)组成,在每个卡片上,我都有一个从项目的嵌套数组对象渲染的表格。当我通过创建一个具有更新数组的新项并将新的项列表设置为状态来将元素添加到项中的嵌套数组时,它不会触发子组件中表的重新呈现。 这是我拥有的代码的粗略示例:

父组件

const Items = () => {
  // Fetching items in useEffect via API call
  const [itemsList, setItemsList] = useState([]);
  
  // This method is called in this component to add row to an item,
  // but I did not include this part to keep the example concise.
  const addRowToItem = (row, itemId) => {
    setItemsList(itemsList.map((item) => {
      if (item.id === itemId) {
        return {...item, rows: item.rows.concat(row)};
      }
      return item;
    }
  }

  return (
    <div>
      {itemsList.map((item) => (
        <ItemCard item={item} />
      )}
    </div>
  );
}

子组件 (ItemCard)

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

  return (
    <div>
      {item.rows.map((row) => (
        // Table row  
      )}
    </div>
  );
}
javascript reactjs 数组 typescript dom

评论


答:

-1赞 Karim Ben Yezza 10/6/2023 #1

在赋值时,您可以使用 代替 ,或者使用 spread 运算符克隆状态对象,如下所示:useReduceruseState

const addRowToItem = (row, itemId) => {
    setItemsList([...itemsList.map((item) => {
      if (item.id === itemId) {
        return {...item, rows: item.rows.concat(row)};
      }
      return item;
    }])
  }

评论

0赞 Nick Parsons 10/6/2023
这里并不是真正必要的,因为已经创建了一个新数组,因此没有必要克隆它。问题在于 OP 是从子组件中的 props 创建状态,在最初设置状态后不会更新。[... ].map()
3赞 Reza 10/6/2023 #2

子组件 (ItemCard) 内部: 无需再次定义。您可以直接使用道具。删除第二行,然后:useState

{props.item.rows.map((row) => (
    // Table row  
  )}

我创建了一个沙盒,你看看它:https://codesandbox.io/s/spring-breeze-ykzfln?file=/src/App.js

评论

0赞 Tushar Walzade 10/6/2023
+1,子项仅采用初始值,并且在道具更新时不会更新。您也可以在效果中更新它,但最好的方法是@Reza提到的 - 直接从道具中使用它useStateitem