简体   繁体   English

React:在加载图像时显示加载微调器

[英]React: Show loading spinner while images load

I have a React app which makes a call in useEffect to my API which returns a list of URLs to use as imy image srcs.我有一个 React 应用程序,它在useEffect中调用我的 API,它返回一个 URL 列表以用作 imy 图像源。

I am using react-loader-spinner to show a loading spinner component while my images load.我正在使用react-loader-spinner在我的图像加载时显示加载微调器组件。

I have a loading variable in useState to determine whether the images are loading.我在useState中有一个loading变量来确定图像是否正在加载。

I can not figure out how to stop showing the loading spinner and show my images once they have all loaded.我无法弄清楚如何停止显示加载微调器并在它们全部加载后显示我的图像。

Here is my code:这是我的代码:

Photos.jsx照片.jsx

import React, { useState, useEffect, Fragment } from 'react'
import Loader from 'react-loader-spinner';
import { getAllImages } from '../../services/media.service';
import Photo from '../common/Photo';

const Photos = () => {
  const [photos, setPhotos] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
      setLoading(true);
      getAllImages()
        .then(results => {
          setPhotos(results.data)
          console.log(results.data)
        })
        .catch(err =>{
          console.log(err)
        })
  }, [])

  const handleLoading = () => {
    setLoading(false)
  }

  return ( 
    <Fragment>
      <div className="photos">
          { loading ? 
            <Fragment>
              <Loader
                height="100"    
                width="100"
              />
              <div>Loading Joe's life...</div>
            </Fragment>
            :
            photos.map((photo, index) => (
                index !== photos.length - 1 ? 
                <Photo src={photo.src} key={photo.id} /> :
                <Photo src={photo.src} key={photo.id} handleLoad={handleLoading}/>
            ))
          }
      </div>
    </Fragment>
   );
}

export default Photos;

Photo.jsx照片.jsx

import React from 'react'

import './Photo.css';

const Photo = (props) => {
  return ( 
    <div className="photo">
      <img src={props.src} alt={props.alt} onLoad={props.handleLoad}/>
      <div className="caption">
        Photo caption
      </div>
    </div>
   );
}

export default Photo;

I tried using onLoad for my last item but it will never get called because loading is never set back to false due to the spinner still being shown.我尝试将onLoad用于我的最后一个项目,但它永远不会被调用,因为由于微调器仍在显示, loading永远不会设置回 false。

Some help on this would be greatly appreciated.在这方面的一些帮助将不胜感激。 Thanks谢谢

The reason why onLoad was never called, is because you never had the images in the DOM, so instead of conditionally rendering, conditionally set the display property to none & block.之所以从未调用 onLoad,是因为您从未在 DOM 中拥有图像,因此与其有条件地渲染,不如有条件地将 display 属性设置为 none & block。

Below is a simple example of how you could wait for all images to load.下面是一个如何等待所有图像加载的简单示例。

Safe to assume the image with the largest file size would most likely be the last to load可以安全地假设具有最大文件大小的图像很可能是最后加载的

Most certainly not!!, the time it takes for an image to load is not always down to size, caching, or server load can effect these.肯定不是!!,加载图像所需的时间并不总是取决于大小、缓存或服务器负载会影响这些。

 const {useState, useEffect, useRef} = React; const urls = [ "https://placeimg.com/100/100/any&rnd=" + Math.random(), "https://placeimg.com/100/100/any&rnd=" + Math.random(), "https://placeimg.com/100/100/any&rnd=" + Math.random() ]; function Test() { const [loading, setLoading] = useState(true); const counter = useRef(0); const imageLoaded = () => { counter.current += 1; if (counter.current >= urls.length) { setLoading(false); } } return <React.Fragment> <div style={{display: loading ? "block" : "none"}}> Loading images, </div> <div style={{display: loading ? "none" : "block"}}> {urls.map(url => <img key={url} src={url} onLoad={imageLoaded}/>)} </div> </React.Fragment>; } ReactDOM.render(<React.Fragment> <Test/> </React.Fragment>, document.querySelector('#mount'));
 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id="mount"></div>

How are they?他们怎么样? Thank you for helping.感谢您的帮助。 I have it as the Keith solutions, but it still doesn't call the onLoad function.我把它作为 Keith 解决方案,但它仍然没有调用 onLoad 函数。 The only way for it to work and trigger onLoad is that instead of display, use visibility over the img parent tag.它工作并触发 onLoad 的唯一方法是使用 img 父标签的可见性而不是显示。 I would like it to work with display prop我希望它与显示道具一起使用

<div style={{visibility: loading ? "hidden" : "visible"}}>
  {urls.map(url => 
    <img 
      key={url}
      src={url}
      onLoad={imageLoaded}/>)}
</div>

just create and component like this and load anywhere that you want to using image:只需像这样创建和组件并加载到您想要使用图像的任何地方:

import React from 'react'
import { useState } from 'react';

export default function MyImage({src, width, size}) {
    const [loading, setLoading] = useState(true);
    return (
    <div style={
        {
            display: "flex",
            justifyContent: "center",
            alignItems: "center",
            width: width?width:"100%",
        }
    } >
    <img src={src} style={
        {
            display: loading?"none":"block",
            width:"100%",
            animation: "fadeIn 0.5s",
        }
    } onLoad={(e)=>{setLoading(false)}}></img>
    <div className="spinner" style={{
        display: loading?"block":"none",
        fontSize: size?size:"24px"
    }} ></div>
</div>)}

you just need define a css class as "spinner" for spinner and an animation as "fadeIn" for image if you want more ui effect.如果您想要更多的用户界面效果,您只需将 css class 定义为微调器的“微调器”,将 animation 定义为图像的“淡入”。 usage:用法:

<MyImage src="link/to/image" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM