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

如何避免数组更新时其元素组件重复渲染?

解决卡片组件重复渲染问题

你的问题核心出在组件定义位置、key的选择、事件函数稳定性这三个点上,以下是具体修复方案:

关键问题分析

  • Card组件定义在App内部,每次App状态更新重渲染时,Card都会被重新定义为新的组件类型,导致所有卡片被迫重渲染。
  • 使用index作为组件key,增删卡片时key会发生变化,React无法正确识别已有组件的身份,触发不必要的重渲染。
  • handleRemove函数每次App渲染都会重新创建,作为props传给Card后,会被识别为新的props,导致Card触发重渲染。

修复步骤及完整代码示例

import "./styles.css";
import React, { useState, useCallback, memo } from "react";

const fakeData1 = {
  Card1: [1, 2, 3, 4]
};
const fakeData2 = {
  Card2: [5, 6, 7, 8]
};

// 用React.memo包裹,仅在props浅变化时重渲染
const Card = memo(({ id, item, onRemove }) => {
  console.log("Rendering Card: ", item);

  const handleRemove = (event) => {
    if (event.type === "click" || event.type === "keydown") {
      onRemove(id);
    }
  };

  return (
    <div style={{ border: "black solid 2px", padding: "50px 0", margin: "10px 0" }}>
      <h1>Card - {id}</h1>
      <div>Content: {Object.values(item)}</div>
      <button onClick={handleRemove}>Remove</button>
    </div>
  );
});

export default function App() {
  const [cardMap, setCardMap] = useState({ fakeData1 });

  // useCallback缓存函数,保证引用稳定
  const addCard = useCallback(() => {
    setCardMap(prev => ({
      ...prev,
      fakeData2
    }));
  }, []);

  const handleCardRemove = useCallback((cardId) => {
    setCardMap(prev => {
      const updated = { ...prev };
      delete updated[cardId];
      return updated;
    });
  }, []);

  return (
    <div className="App">
      <button onClick={addCard}>Add a Card</button>
      {Object.entries(cardMap).map(([cardId, item]) => {
        // 使用数据唯一标识作为key,避免index导致的重渲染
        return <Card key={cardId} id={cardId} item={item} onRemove={handleCardRemove} />;
      })}
    </div>
  );
}

改动说明

  • React.memo包裹Card:让Card组件仅在props发生浅变化时才触发重渲染。
  • Card移到App外部:保证组件类型稳定,不会因为App重渲染而被重新定义。
  • 使用数据唯一标识当key:用fakeData1、fakeData2作为key,增删操作时已有卡片的key不会变化,React能正确复用组件。
  • useCallback缓存事件函数:addCard和handleCardRemove用useCallback包裹,确保函数引用稳定,不会作为新props触发Card重渲染。
  • 改用对象存储卡片:用对象替代数组存储卡片,更方便通过key进行增删操作,也避免了flat处理的额外开销。

现在测试时,新增或移除卡片只会触发对应卡片的渲染日志,未改动的现有卡片不会重复打印渲染信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 04:00:35