【发布时间】:2021-01-13 11:15:30
【问题描述】:
我有一个 PlayArea 组件,其中包含许多 Card 组件作为子组件,用于纸牌游戏。
纸牌的位置由 PlayArea 管理,它有一个名为 cardsInPlay 的状态值,它是一个 CardData 对象数组,包括位置坐标等。 PlayArea 将 cardsInPlay 和 setCardsInPlay(来自 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} />);
});
【问题讨论】:
-
确保在将
cardsInPlay数组映射到 JSX 时提供正确的key属性以避免不必要地重新挂载实例,并将Card组件包装在React.memo()中HOC。 -
这很奇怪,我已经拥有了这两个。
-
您的意思是
const Card = ({ card, cardsInPlay, setCardsInPlay }) => ...?注意在参数列表中添加了对象解构{ ... }。 -
哦,是的。我在实际代码中没有任何类似的问题——这只是简化时的一个错字。我现在也将备忘录/密钥添加到示例代码中。
-
问题是您将 整个
cardsInPlay数组传递给每个Card,因此道具 do 会发生变化。只传递每张卡片需要知道的元素。并使用功能性setCardsInPlay()签名来访问之前的状态。你不需要传递整个数组来获得它。
标签: javascript reactjs react-props use-state react-state