React image onLoad, image preload

Есть картинка на первом экране страницы, при медленном интернете вместо картинки ничего нет (пустое белое пространство в высоту картинки). Нужно до полной загрузки картинки показывать какую-нибудь анимацию, как отловить полную загрузку картинки?

 <img
    className={classes.image}
    src="/images/vacancies/image.png"
    alt="image"
    onLoad={() => console.log('loaded')} // Это не срабатывает
  />

Пока использую:

  useEffect(() => {
    setIsLoaded(true)
  }, [])

И в зависимости от значения isLoaded показываю либо картинку, либо заглушку. Этот способ не спасает от частичной загрузки изображения при медленном интернете (сначала появляется заглушка, потом - белый фон, потом сверху вниз по чуть-чуть отрисовывается отображение).

Как отображать изображение сразу после его загрузки (сначала появляется заглушка, потом появляется полное изображение)?


Ответы (1 шт):

Автор решения: Vladimir

Это не так просто, но и не так сложно.
Для того чтобы показать картинку только после загрузки

  1. Надо ее загрузить используя fetch или любой другой загрузчик
  2. Пока ждем ответа показываем анимацию
  3. После того как картинка загрузилась преобразовываем ее с помощью blob и createObjectURL в урл
  4. Вставляем урл в атрибут src

const { useEffect, useState } = React;

const Img = () => {
  const [url, setUrl] = useState('');
  useEffect(() => {
    fetch('https://images.unsplash.com/photo-1490730141103-6cac27aaab94')
      .then(response => response.blob())
      .then((image) => {
        setUrl(URL.createObjectURL(image));
      });
  });
  
  if (!url) {
    return 'animations...';
  }
      
  return <img src = {url}/>;
}

ReactDOM.render( 
  <Img /> ,
  document.getElementById('app')
);
  <script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>

<div id="app"></div>

→ Ссылка