Gatsby / React:如何防止在更改display:none元素的背景图像时发生这种重绘?

时间:2019-09-29 08:15:02

标签: reactjs react-hooks gatsby repaint memoization

已编辑:根据@HMR的回答,我会提出他的建议并提供完整的代码

如果我有这样的组件

const wait = ...
cosnt get_new_wallpaper = ... // it changes pool_of_images_fetched

const Wallpaper = () => {
  const [background, setBackground] = useState()
  const [nextBackground, setNextBackground] = useState()
  const [visible, setVisible] = useState('first') // not changed in this example
  const [pool_of_images_fetched, setPool_of_images_fetched] = useState([])


  const setNewWallpaper = useCallback(async stillMounted => {
    const wallpaper = await get_new_wallpaper(
     pool_of_images_fetched,
     setPool_of_images_fetched
    )
    stillMounted.value && setBackground(wallpaper)

    await wait(2000)
    const wallpaper2 = await get_new_wallpaper(
     pool_of_images_fetched,
     setPool_of_images_fetched
    )
    stillMounted.value && setNextBackground(wallpaper2)
  }, [])

  useEffect(() => {
    let stillMounted = {value: true}
    const init_new_wallpaper = async () => await setNewWallpaper (stillMounted)
    init_new_wallpaper()
    return function cancel() {
      stillMounted.value = false
    }
  }, [])

  return (
   <>
    <PureFirst background={background} onClick={setNewWallpaper} />
    <PureSecond background={nextBackground} onClick={setNewWallpaper} />
   </>
  )
}

const First = styled.div`
  display: ${props => (props.visible === 'first' ? 'unset' : 'none')};
  background-image: url('${props => props.background}');
`
const Second = styled.div`
  display: ${props => (props.visible === 'second' ? 'unset' : 'none')};
  background-image: url('${props => props.background}');
`
const PureFirst = memo(First)
const PureSecond = memo(Second)

setNewWallpaper()更改background时,我看到<First>相应地发生变化,然后等待2秒,然后当nextBackground更改时,我也看到<Second>相应地发生变化

如您所见,<First>是可见的(display:unset;),而<Second>是看不见的(display:none;

问题 ,这是<First>更改后<Second>会重新绘制,即使看不见<Second>,所以发生了 flash 在这2秒钟后进入网站

为什么在这里没有记住此代码?

2 个答案:

答案 0 :(得分:1)

您可以使用React.memo首先使第二个组件成为纯组件,然后使用useCallback确保setNewWallpaper不会在渲染之间更改引用。

我不知道setNewWallpaper的依赖项是什么,因为您没有发布所有代码,所以我假设没有:

const PureFirst = React.memo(First);
const PureSecond = React.memo(Second);
export const Wallpaper = () => {
  const [background, setBackground] = useState();
  const [nextBackground, setNextBackground] = useState();

  const setNewWallpaper = useCallback(async () => {
    setBackground(...);
    await wait(2000);
    setNextBackground(...);
  }, []);

  return (
    <>
      <PureFirst
        background={background}
        onClick={setNewWallpaper}
      />
      <PureSecond
        background={nextBackground}
        onClick={setNewWallpaper}
      />
    </>
  );
};

答案 1 :(得分:0)

结束这个问题,最后,由于打开开发人员工具并单击 disable cache

而导致闪存刷新

没有它,就不会重涂