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

Gatsby/React: How to prevent this repaint that occurs when chanding background-image of a display:none element?

已编辑:根据@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;)

这里的问题是当<Second>改变时<First>被重新绘制,即使<Second>是看不见的,所以发生的事情是2 秒后 flash

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

您可以使用 React.memo and use useCallback 将 first 和 second 设为纯组件,以确保 setNewWallpaper 不会在渲染之间更改引用。

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

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}
      />
    </>
  );
};

关闭问题,最后闪现是由于打开了开发者工具导致的,然后点击了禁用缓存

没有它,不重绘