Рендеринг изображений внутри стилизованного компонента при открытом Chrome Dev Tools - PullRequest
1 голос
/ 31 октября 2019

Это немного странно, и я не уверен, почему это происходит точно.

Когда компонент монтируется, я вызываю функцию, которая в моем приложении делает HTTP-запрос для получения массива объектов. Затем я обновляю 3 состояния в методе карты.

enquiries - это просто ответ от HTTP-запроса activeProperty - который определяет, какой идентификатор объекта является текущим активным 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 я отрисовываю два изображения из details реквизита на основе состояния channelDetails

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 изображения, которые мигают / перерисовывают. Я думал, что алгоритм diff включился бы здесь и не перерисовал бы изображения, поскольку они - те же самые изображения?

Но кажется, что styled-components добавляет новый класс каждый раз, когда вы нажимаете на ChannelListItem, так что он перерисовывает изображение. Но ТОЛЬКО когда открыто окно инструментов разработки?

Почему это так? Есть ли способ обойти это?

Я могу использовать встроенные стили вместо styled-components, и он работает, как и ожидалось, хотя я хотел посмотреть, есть ли способ обойти это без удаления styled-components

У меня есть CODESANDBOX , чтобы проверить себя

Ответы [ 2 ]

1 голос
/ 31 октября 2019

Если вы повторно активируете cache в devtool на вкладке сети, проблема исчезнет.

Таким образом, возникает вопрос, почему браузер обновляет изображение, когда кэш отключен;)

Этопросто потому, что 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;
1 голос
/ 31 октября 2019

Я думаю, что это связано с этим параметром, чтобы отключить кэш (см. Красную маркировку на изображении)

enter image description here

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...