我正在创建一个简单的Magic The Gathering搜索引擎。愿景是列出搜索结果,单击搜索结果后,主显示屏将提供有关所选卡的扩展信息。
最顶层的App
组件包含要显示的卡片的状态,而ScrollView
组件则保留仅针对突出显示列表中所选卡片的所选卡片的状态。我向下传播setDisplayCard
处理程序,以便在列表中单击显示卡时,可以将显示显示卡设置为回调。
function App(props) {
const [displayCard, setDisplayCard] = useState(null)
return (
<div className="App">
<SearchDisplay handleCardSelect={setDisplayCard}/>
<CardDisplay card={displayCard} />
</div>
);
}
function SearchDisplay({handleCardSelect}) {
const [cards, setCards] = useState([]);
useEffect(() => {
(async () => {
const cards = await testCardSearch();
setCards(cards);
})();
}, []);
async function handleSearch(searchTerm) {
const searchCards = await cardSearch({name: searchTerm});
setCards(searchCards)
};
return (
<StyledDiv>
<SearchBar
handleSubmit={handleSearch}
/>
<ScrollView
handleCardSelect={handleCardSelect}
cards={cards}
/>
</StyledDiv>
);
}
function ScrollView({cards, handleCardSelect}) {
const [selected, setSelected] = useState(null);
return (
<ViewContainer>
{cards.map((card, idx) =>
<li
key={idx}
style={selected === idx ? {backgroundColor: "red"} : {backgroundColor: "blue"}}
onClick={() => {
setSelected(idx);
handleCardSelect(card);
}}
>
<Card card={card} />
</li>
)}
</ViewContainer>
);
}
我遇到的问题是,致电setDisplayCard
重新提供我的ScrollView
并消除了所选卡的本地状态,因此我无法在列表中突出显示活动卡。根据我对react的理解,我不明白为什么ScrollView
重新呈现,因为它不依赖于displayCard
的状态。我不确定采取什么方法来解决它。当我单击列表中的卡时,我希望它突出显示红色。
答案 0 :(得分:0)
默认情况下(无状态)组件会在3种情况下重新渲染
对于组件,可以使用shouldComponentUpdate
,对于无状态组件,可以使用memo
来更改此行为。
// If this function returns true, the component won't rerender
areEqual((prevProps, nextProps) => prevProps.cards === nextProps.card)
export default React.memo(ScrollView, areEqual);
但是我认为这不是您的问题。您正在使用数组索引idx
作为元素键,这通常会导致意外行为。
尝试删除key={idx}
,然后检查是否可以解决您的问题。
答案 1 :(得分:0)
子组件的render
方法一旦被调用,它的父组件的render方法将被调用。如果道具或状态发生变化,也是如此。
由于您正在使用功能组件,因此可以使用React.memo
HOC来防止不必要的组件重新出售。
React.memo
的行为类似于PureComponent
,并且将ScrollView
的旧props
与新props
进行浅表比较,并且仅在以下情况下触发重新渲染他们不平等:
export default React.memo(ScrollView);
React.memo
也有第二个参数,它使您可以控制比较:
function areEqual(prevProps, nextProps) {
// only update if a card was added or removed
return prevProps.cards.length === nextProps.cards.length;
}
export default React.memo(ScrollView, areEqual);
如果您要使用基于类的组件,则也可以使用shouldComponentUpdate
生命周期方法。
答案 2 :(得分:-2)
因此,您的App组件应该保留用户单击的卡的状态?现在,您的App组件是无状态的。这是一个功能组件。尝试将其转换为具有初始状态和维护状态的类组件。
setDisplayCard()的逻辑是什么?
我在React 16中听说过吗?诸如“ useState()”和“挂钩”之类的东西,但我对此并不熟悉。
这个人似乎也有类似的问题,