React svg / png render is flickering on new URL

筅森魡賤 提交于 2021-02-08 19:53:31

问题


I'm using latest create-react-app config and facing the issues when switching between different routes.

All my SVG's are included in sprite file. Logically, sprite.svg file should be cached on the first-page load.

But instead, every change of route (with react-router 4) loads this file which causes flickering. Content changes instantly, but images loads with 1s lag. Same for png included via import in jsx.

From what I cant see in the console, same files download over and over again.

Live demo at http://cabin.surge.sh/ (i.e. try to change between Pricing / About pages in the header section)

Update:

The way I include SVG image - is dumb component <SvgIcon name="checkmark" />

import React, { Component } from 'react';
import sprite from '../images/sprite.svg';

export default class SvgIcon extends Component {
  render(){
    const { name } = this.props;
    return(
      <svg className={"ico ico-" + name}>
        <use xlinkHref={sprite + "#ico-" + name}></use>
      </svg>
    )
  }
}

PNG images

<img src={require(`../images/${authorImage}.png`)} srcSet={require(`../images/${authorImage}@2x.png`)  + ' 2x'} alt=""/>

回答1:


The reason you get a 200 instead of 304 is that you have a service worker which will intercept the request and serve the same from the cache itself. Which itself is 200 response. If you disable the service worker then you will get a 304




回答2:


If the problem is that the image is not fetched earlier and causing flickering on page change, try to use

componentDidMount() {
  const sprite = "../images/sprite.svg";
  const prefetchLink = document.createElement("link");

  prefetchLink.href = sprite;
  prefetchLink.rel = "prefetch";
  prefetchLink.as = "image";
  document.body.appendChild(prefetchLink);
}

This will hint the browser to fetch resources in the background (idle time) that might be needed later, and store them in the browser’s cache. Once a page has finished loading it begins downloading additional resources and if a user then clicks on a prefetched link, it will load the content instantly.

For a functional version:

//custom hook to preload image
const usePreload = (url) => {
  const [loaded, setLoaded] = React.useState(false);
  const onLoad = React.useCallback(() => {
    setLoaded(true);
  }, []);
  React.useEffect(() => {
    const prefetchLink = document.createElement('link');
    prefetchLink.href = url;
    prefetchLink.rel = 'prefetch';
    prefetchLink.as = 'image';
    prefetchLink.addEventListener('load', onLoad);
    document.body.appendChild(prefetchLink);
    //clean up
    return () => document.body.removeChild(prefetchLink);
  }, [onLoad, url]);
  return loaded;
};

export default function SvgIcon({ name }) {
  const url = sprite + '#ico-' + name;
  const loaded = usePreload(url);
  return (
    loaded && ( //only render if image is loaded
      <svg className={'ico ico-' + name}>
        <use xlinkHref={url}></use>
      </svg>
    )
  );
}

Note that if you do server side rendering you don't want this code to execute on the server because there is no document on the server.



来源:https://stackoverflow.com/questions/50659679/react-svg-png-render-is-flickering-on-new-url

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!