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

React中如何更新状态数组映射的嵌套组件,避免全量重新渲染?

问题根因

你之前用React.memo不生效主要是两个常见问题:

  • 每次Board组件重渲染时,addCard、addList函数都会重新生成,引用地址变化,导致List组件接收的addCardprop每次都不同,React.memo的浅比较直接判定需要重渲染
  • 更新lists状态时如果做了全量深拷贝,所有列表对象的引用都会变化,哪怕内容没改的列表也会被判定为props变化,触发重渲染

无需引入Redux的优化方案

只用React自带的API就能解决,按以下步骤修改即可:

1. 用useCallback固定回调函数引用

给addList、addCard包裹useCallback,状态更新用函数式写法,不需要依赖外部lists变量,依赖项设为空数组,保证函数引用永远不变:

const addList = useCallback((listTitle) => {
  // 调用新增列表接口成功后更新状态
  api.addList(listTitle).then(newList => {
    setLists(prev => [...prev, newList])
  })
}, [])

const addCard = useCallback((listId, cardText) => {
  // 调用新增卡片接口成功后更新状态
  api.addCard(listId, cardText).then(newCard => {
    setLists(prevLists => {
      // 只修改目标列表的引用,其他列表保持原引用
      return prevLists.map(list => {
        if (list.listId === listId) {
          return {
            ...list,
            cards: [...list.cards, newCard]
          }
        }
        return list
      })
    })
  })
}, [])

2. 组件添加React.memo

List和Card都包裹React.memo,注意修正你原来List组件里的笔误:遍历的变量应该是传入的cards不是listCards:

// List组件
const List = React.memo(({ title, cards, listId, addCard }) => {
  return (
    <section>
      <h2>{title}</h2>
      <ul>
        {cards.map((card) => <Card key={card.cardId} text={card.cardText} />)}
      </ul>
      <AddElementPanel listId={listId} addElement={addCard} />
    </section>
  )
})

// Card组件
const Card = React.memo(({ text }) => {
  return <li>{text}</li>
})

优化效果

修改完成后:

  • 新增列表时,只有新的列表会触发渲染,原有所有列表、卡片都不会重渲染
  • 给某个列表新增卡片时,只有目标列表和新增的卡片会触发渲染,其他列表、该列表下原有卡片都不会重渲染
    如果后续要做拖拽功能,也可以用同样的不可变更新逻辑,只修改移动涉及的两个列表的引用即可,不会触发全量重渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 00:45:03