Как предварительно загрузить изображение в компонент React JS?

В настоящее время я визуализирую дочерний компонент при возникновении signInError. signInError хранится в родительском компоненте, и если он не равен нулю, он отображает компонент <SignInError/> в соответствии с приведенным ниже кодом:

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

RoundImage.js

import React from 'react';

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

export default RoundImage;

Как предварительно загрузить изображения в React.js?

Ответ на этот вопрос (ссылка выше) здесь, в Stack Overflow, говорит мне создать объект img внутри метода componentDidMount(), чтобы браузер загрузил его. Я так и сделал, как вы можете видеть из приведенного выше кода. Но теперь, когда я пытаюсь передать его в качестве опоры моему внучатому компоненту внутри моего метода render, я не могу получить доступ к img, потому что он был определен внутри другого метода.

Как лучше всего обойти это? Мне просто нужно, чтобы изображение было загружено и отображалось вместе с сообщением об ошибке. В противном случае сообщение об ошибке будет отображаться перед изображением, если ваш браузер еще не кэшировал его. Спасибо за помощь.

Что такое «RoundImage»?

Diodeus - James MacFarlane 08.01.2019 17:37

Если RoundImage ожидает путь, почему бы просто не использовать: <RoundImage src = {Newman}/>?

Diodeus - James MacFarlane 08.01.2019 17:41

Я только что отредактировал, чтобы добавить код RoundImage.js. Спасибо.

cbdeveloper 08.01.2019 17:41

@ Diodeus-JamesMacFarlane Я пробовал это. Он работает, но не загружает мое изображение заранее. "Привет, Ньюман!" отображается перед изображением. А затем, как только браузер загрузит его, он загрузится ...

cbdeveloper 08.01.2019 17:43

Если вы хотите предварительно загрузить его, вам нужно создать новый Image () выше в вашем приложении. К моменту загрузки компонента изображение все еще отсутствует. Вам не нужно ссылаться на это изображение, вы просто хотите, чтобы браузер загрузил его. Когда вы используете его в своем компоненте, он уже будет кэширован.

Diodeus - James MacFarlane 08.01.2019 17:47
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
5
5
20 222
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Немного другой подход, но если у вас есть источник изображения заранее, вы можете добавить источник изображения в основной файл html в качестве ссылки с опцией предварительной загрузки. Браузер предварительно загрузит изображение (с относительно низким приоритетом), и когда ваше приложение загрузит изображение, оно должно быть кэшировано в памяти браузера.

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

В этом подходе мы отделяем процесс предварительной загрузки от кода. Это более актуально, когда у вас есть источник изображения заранее (а не динамически) и когда вам не нужно кэшировать большое количество изображений (будет немного беспорядочно добавлять большой список ссылок в заголовок html, хотя возможный)

вы можете узнать больше о предварительной загрузке ссылок здесь: Предварительная загрузка содержимого с помощью rel = "preload"

Спасибо за вашу помощь. Однако мне действительно нужно, чтобы это было внутри компонента.

cbdeveloper 08.01.2019 17:54

Я уже импортирую его в import Newman from '../../../../assets/newman-min.png'; Обмотка require какая разница?

cbdeveloper 08.01.2019 18:14

Нет, на самом деле его эквивалент (:

Dan Porat 08.01.2019 18:32
Ответ принят как подходящий

Загрузка изображения происходит в браузере. Рендеринг в DOM также происходит в браузере.

Под предварительная загрузка вы имеете в виду, что хотите, чтобы компонент отображался только тогда, когда изображение готово?

Если да, вы можете сделать что-то вроде этого:

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

Это то, что я искал. Просто изменил this.state({ imageIsReady: true }); вашего ответа на this.setState(...), и он работает так, как я задумал. Большое спасибо.

cbdeveloper 08.01.2019 18:11

Ах да, спасибо за исправление. Я исправил опечатку в своем ответе.

Jackyef 09.01.2019 04:22
img.src следует размещать после img.onload. В противном случае вы рискуете, что onload не запустится, если изображение будет кэшировано в браузере.
Eksapsy 10.01.2021 17:40

В моем случае я начинаю с начального атрибута 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];
};

Другие вопросы по теме