Реагировать: Показать загрузчик при загрузке изображений - PullRequest
0 голосов
/ 05 июля 2019

У меня есть приложение React, которое вызывает в useEffect мой API, который возвращает список URL-адресов для использования в качестве изображений imy.

Я использую react-loader-spinner, чтобы показать загружаемый компонент счетчикапока мои изображения загружаются.

У меня есть переменная loading в useState, чтобы определить, загружаются ли изображения.

Я не могу понять, как перестать показывать загрузочный счетчик и показывать мои изображения, как только онивсе загружено.

Вот мой код:

Photos.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

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;

Я пытался использовать onLoad для моего последнего элемента, но он никогда не будет вызван, потому что loading никогда не сбрасывается в false из-за показа счетчика.

Некоторая помощь по этому вопросу будет принята с благодарностью.Спасибо

1 Ответ

1 голос
/ 05 июля 2019

Причина, по которой onLoad никогда не вызывался, заключается в том, что у вас никогда не было изображений в DOM, поэтому вместо условного рендеринга установите для свойства display значение none & block.

Ниже приведен простой примеркак вы могли бы ждать загрузки всех изображений.

Можно предположить, что изображение с наибольшим размером файла, скорее всего, будет последним загружать

Скорее всего, нет!!, время, необходимое для загрузки изображения, не всегда зависит от размера, это может повлиять на кэширование или загрузку сервера.

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>
...