首页 > 解决方案 > 当某个道具发生变化时,如何避免重新渲染功能组件?

问题描述

我有一个 PlayArea 组件,其中包含许多 Card 组件作为子组件,用于纸牌游戏。

牌的位置由 PlayArea 管理,它有一个名为 的状态值cardsInPlay,它是一个CardData对象数组,包括位置坐标等。PlayArea 将cardsInPlayand setCardsInPlay(from useState) 传递到每个 Card 子组件中。

卡片是可拖动的,在拖动时它们会调用setCardsInPlay以更新自己的位置。

结果当然是cardsInPlay改变了,因此每张卡片都会重新渲染。如果一百张牌出现在桌面上,这可能会增加成本。

我怎样才能避免这种情况?PlayArea 和 Card 都是功能组件。

这是该描述的简单代码表示:

const PlayArea = () => {
  const [cardsInPlay, setCardsInPlay] = useState([]);

  return (
    <>
      { cardsInPlay.map(card => (
        <Card
          key={card.id}
          card={card}
          cardsInPlay={cardsInPlay}
          setCardsInPlay={setCardsInPlay} />
      }
    </>
  );
}

const Card = React.memo({card, cardsInPlay, setCardsInPlay}) => {
    const onDrag = (moveEvent) => {
       setCardsInPlay(
         cardsInPlay.map(cardInPlay => {
           if (cardInPlay.id === card.id) {
              return {
               ...cardInPlay,
               x: moveEvent.clientX,
               y: moveEvent.clientY
              };
           }
           return cardInPlay;
        }));
      };

      return (<div onDrag={onDrag} />);
   });

          

标签: javascriptreactjsreact-propsuse-statereact-state

解决方案


这取决于您如何传递cardsInPlay给每个Card组件。只要您只将所需的信息传递给孩子,状态中的数组是否发生变化都没有关系。

例如:

<Card positionX={cardsInPlay[card.id].x} positionY={cardsInPlay[card.id].y} /> 

不会导致重新渲染,因为即使父数组发生更改,实例本身也不会获得新的道具。但是,如果您将整个数据传递给每个组件:

<Card cardsInPlay={cardsInPlay} /> 

它将导致所有人重新渲染,因为每个渲染Card都会获得一个新的道具,因为没有两个数组,对象在 Javascript 中是相等的。

PS:看到示例代码后编辑


推荐阅读