【发布时间】:2020-02-26 19:53:44
【问题描述】:
这有点奇怪,不知道为什么会这样。
当组件挂载时,我调用一个函数,该函数在我的应用程序中发出 HTTP 请求以获取对象数组。然后我在 map 方法中更新 3 个状态。
enquiries - 这只是来自 HTTP 请求的响应
activeProperty - 定义当前活动的对象 ID
channelDetails - 解析一些响应数据以用作传递给子组件的道具。
const [enquiries, setEnquiries] = useState({ loading: true });
const [activeProperty, setActiveProperty] = useState();
const [channelDetails, setChannelDetails] = useState([]);
const getChannels = async () => {
// In my actual project,this is an http request and I filter responses
const response = await Enquiries;
const channelDetailsCopy = [...channelDetails];
setEnquiries(
response.map((e, i) => {
const { property } = e;
if (property) {
const { id } = property;
let tempActiveProperty;
if (i === 0 && !activeProperty) {
tempActiveProperty = id;
setActiveProperty(tempActiveProperty);
}
}
channelDetailsCopy.push(getChannelDetails(e));
return e;
})
);
setChannelDetails(channelDetailsCopy);
};
useEffect(() => {
getChannels();
}, []);
然后我返回一个子组件ChannelList,它使用样式化组件向元素添加样式并呈现子元素。
const ChannelList = ({ children, listHeight }) => {
const ChannelListDiv = styled.div`
height: ${listHeight};
overflow-y: scroll;
overflow-x: hidden;
`;
return <ChannelListDiv className={"ChannelList"}>{children}</ChannelListDiv>;
};
在ChannelList 组件内部,我映射enquiries 状态并渲染ChannelListItem 组件,该组件在数组内对象的索引上具有分配的键,并接受channelDetails 状态和onClick处理程序。
return (
<>
{enquiries &&
enquiries.length > 0 &&
!enquiries.loading &&
channelDetails.length > 0 ? (
<ChannelList listHeight={"380px"}>
{enquiries.map((enquiry, i) => {
return (
<ChannelListItem
key={i}
details={channelDetails[i]}
activeProperty={activeProperty}
setActiveProperty={id => setActiveProperty(id)}
/>
);
})}
</ChannelList>
) : (
"loading..."
)}
</>
);
在ChannelListItem 组件中,我根据channelDetails 状态从details 属性渲染两个图像
const ChannelListItem = ({ details, setActiveProperty, activeProperty }) => {
const handleClick = () => {
setActiveProperty(details.propId);
};
return (
<div onClick={() => handleClick()} className={`ChannelListItem`}>
<div className={"ChannelListItemAvatarHeads"}>
<div
className={
"ChannelListItemAvatarHeads-prop ChannelListItemAvatarHead"
}
style={{
backgroundSize: "cover",
backgroundImage: `url(${details.propertyImage})`
}}
/>
<div
className={
"ChannelListItemAvatarHeads-agent ChannelListItemAvatarHead"
}
style={{
backgroundSize: "cover",
backgroundImage: `url(${details.receiverLogo})`
}}
/>
</div>
{activeProperty === details.propId ? <div>active</div> : null}
</div>
);
};
现在,只要打开 chrome 开发工具窗口并单击不同的 ChannelListItems 图像就会闪烁/重新渲染,就会出现问题。我原以为差异算法会在这里发挥作用,而不是重新渲染图像,因为它们是相同的图像?
但似乎styled-components 每次单击ChannelListItem 时都会添加一个新类,因此它会重新渲染图像。但只有在开发工具窗口打开时?
这是为什么?有没有办法解决这个问题?
我可以使用内联样式而不是 styled-components,它可以按预期工作,但我想看看是否有办法在不删除 styled-components 的情况下解决这个问题
我有一个CODESANDBOX 来检查自己
【问题讨论】: