如何在 React JS 组件中预加载图像?

IT技术 javascript reactjs preload
2021-05-11 08:20:18

我目前正在渲染一个子组件signInErrorsignInError存储在父组件,如果它不为空,它呈现的<SignInError/>组件,如下面的代码:

父组件.js

  // Some code...

  render() {
    return(
      <div>
        <SignInForm
          doSignIn={this.doSignIn}
          resetSignInError={this.resetSignInError}
          signInError={this.state.signInError}
        />
        {this.state.signInError && <SignInError/>}
      </div>
    );
  }

到目前为止,一切都很好,这是子组件 SignInError.js

import React from 'react';
import RoundImage from '../../../UI/Common/RoundImage';
import Newman from '../../../../assets/newman-min.png';

class SignInError extends React.Component {
  constructor(props){
    super(props);
  }

    componentDidMount(){
    const img = new Image();
    img.src = Newman;
  }

  render(){
    return(
      <div>
      <div>
        <RoundImage src={img.src}/> // <--- img is undefined here!!!
      </div>
      <div>
        Hello... Newman!
      </div>
    </div>
    );
  }
}

export default SignInError;

圆形图像.js

import React from 'react';

const RoundImage = (props) => {
  return (
    <div>
      <img src={props.src}/>
    </div>
  );
}

export default RoundImage;

如何在 React.js 中预加载图像?

Stack Over flow 上的这个问题的答案(上面的链接)告诉我imgcomponentDidMount()方法创建对象以强制浏览器加载它。所以我做到了,正如您从上面的代码中看到的那样。但是现在,当我尝试将它作为 prop 传递给我的方法中的孙子组件时render,我无法访问img,因为它是在另一个方法中定义的。

解决这个问题的最佳方法是什么?我只需要加载图像并与错误消息一起显示。否则,如果您的浏览器尚未缓存它,错误消息将显示在图像之前。谢谢您的帮助。

3个回答

图片下载发生在浏览器中。渲染到 DOM 也发生在浏览器中。

通过preloading,您的意思是您希望组件仅在图像准备好时才呈现?

如果是这样,你可以这样做:

componentDidMount() {
  const img = new Image();
  img.onload = () => {
    // when it finishes loading, update the component state
    this.setState({ imageIsReady: true });
  }
  img.src = Newman; // by setting an src, you trigger browser download

}

render() {
  const { imageIsReady } = this.state;

  if (!imageIsReady) {
    return <div>Loading image...</div>; // or just return null if you want nothing to be rendered.
  } else {
    return <img src={Newman} /> // along with your error message here
  }
}

有点不同的方法,但是如果您事先有图像源,则可以将图像源作为带有预加载选项的链接引用添加到主 html 文件中。浏览器将预加载图像(优先级相对较低),并且在您的应用加载图像时,它应该缓存在浏览器内存中。

<head>
..
..
<link rel="preload" href="<your_image_source_here>" as="image">
...
</head>

在这种方法中,我们将预加载过程与代码分开。当您预先拥有图像源(而不是动态)并且不需要缓存大量图像时(在 html 头中添加大量链接列表会有点混乱,尽管可能的)

您可以在此处了解有关链接预加载的更多信息:使用 rel="preload"预加载内容

就我而言,我从图像的初始 src 属性开始,并希望在浏览器加载图像延迟更改它们,因此我在 Typescript 中编写了以下钩子:

import { useEffect, useState } from 'react';

export const useImageLoader = (initialSrc: string, currentSrc: string) => {
  const [imageSrc, _setImageSrc] = useState(initialSrc);

  useEffect(() => {
    const img = new Image();
    img.onload = () => {
      _setImageSrc(currentSrc);
    };
    img.src = currentSrc;
  }, [currentSrc]);

  return [imageSrc];
};