React svg/png 渲染在新 URL 上闪烁 [英] React svg / png render is flickering on new URL

查看:33
本文介绍了React svg/png 渲染在新 URL 上闪烁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用最新的 create-react-app 配置并在不同路由之间切换时遇到问题.

我所有的 SVG 都包含在 sprite 文件中.从逻辑上讲,sprite.svg 文件应该在第一页加载时缓存.

但是,路由的每次更改(使用 react-router 4)都会加载这个文件,这会导致闪烁.内容立即更改,但图像加载延迟 1 秒.与通过 import 包含在 jsx 中的 png 相同.

从我在控制台中看不到的内容来看,相同的文件一遍又一遍地下载.

更新:

我包含 SVG 图像的方式 - 是愚蠢的组件 <SvgIcon name="checkmark"/>

import React, { Component } from 'react';从'../images/sprite.svg'导入精灵;导出默认类 SvgIcon 扩展组件 {使成为(){const { name } = this.props;返回(<svg className={"ico ico-" + name}><use xlinkHref={sprite + "#ico-" + name}></use></svg>)}}

PNG 图片

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

解决方案

如果问题是图片没有提早获取导致页面变化时出现闪烁,请尝试使用

componentDidMount() {const sprite = "../images/sprite.svg";const prefetchLink = document.createElement("link");prefetchLink.href = 精灵;prefetchLink.rel = "预取";prefetchLink.as =图像";document.body.appendChild(prefetchLink);}

这将提示浏览器在后台(空闲时间)获取稍后可能需要的资源,并将它们存储在浏览器的缓存中.页面加载完成后,它会开始下载其他资源,如果用户随后点击预取链接,它将立即加载内容.

对于功能版本:

//自定义钩子预加载图片const usePreload = (url) =>{const [loaded, setLoaded] = React.useState(false);const onLoad = React.useCallback(() => {设置加载(真);}, []);React.useEffect(() => {const prefetchLink = document.createElement('link');prefetchLink.href = url;prefetchLink.rel = '预取';prefetchLink.as = '图像';prefetchLink.addEventListener('load', onLoad);document.body.appendChild(prefetchLink);//清理返回 () =>document.body.removeChild(prefetchLink);}, [onLoad, url]);返回加载;};导出默认函数 SvgIcon({ name }) {const url = sprite + '#ico-' + 名称;const 加载 = usePreload(url);返回 (加载 &&(//仅在加载图像时渲染<svg className={'ico ico-' + name}><use xlinkHref={url}></use></svg>));}

请注意,如果您进行服务器端渲染,您不希望此代码在服务器上执行,因为服务器上没有 document.

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=""/>

解决方案

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.

这篇关于React svg/png 渲染在新 URL 上闪烁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆