【问题标题】:Images Rerendering inside Styled Component when Chrome Dev Tools is open当 Chrome 开发工具打开时,样式化组件内的图像重新渲染
【发布时间】: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 来检查自己

【问题讨论】:

    标签: reactjs styled-components


    【解决方案1】:

    我认为这与禁用缓存的设置有关(见图片中的红色标记)

    希望这会有所帮助。

    【讨论】:

    • 啊,是的!你可能是对的,这也适用于我!
    • 我猜它仍然会重新渲染,但如果没有禁用缓存,它需要足够快的速度才能在重新渲染时不被注意到。
    【解决方案2】:

    如果您在网络选项卡上的 devtool 中重新激活 cache,问题就会消失。

    所以问题变成了为什么禁用缓存时浏览器会重新获取图像;)

    这只是因为 dom 发生了变化,所以浏览器重新渲染它,因为你提到它的类发生了变化。

    所以类发生了变化,因为组件发生了变化。 您在每次渲染时创建一个新组件。

    一个简单的修复:

    import React from "react";
    import styled from "styled-components";
    
    const ChannelListDiv = styled.div`
        height: ${props => props.listHeight};
        overflow-y: scroll;
        overflow-x: hidden;
    `;
    
    
    const ChannelList = ({ children, listHeight }) => {
      return <ChannelListDiv listHeight={listHeight} className={"ChannelList"}>{children}</ChannelListDiv>;
    };
    
    export default ChannelList;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-27
      • 2022-11-20
      • 1970-01-01
      • 2014-09-16
      • 2021-07-21
      • 2012-08-26
      • 2013-08-17
      • 1970-01-01
      相关资源
      最近更新 更多