8

I have a page which contains several images. When the page loads it provides a default image for each IMG:

import default from './pics/default.jpg';

<img src={default} alt="#"/>

What I want is something like this:

<img src1={default} src2="img url" alt="#"/>

Where src2 overwrites src1 when it is loaded.

Edit: The first image (src1) comes as the page loads while the second (src2) is requested trough the internet. Example: https://cdn.pixabay.com/photo/2016/10/17/10/52/wind-farm-1747331__340.jpg

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Laczkó Örs
  • 1,082
  • 1
  • 18
  • 38

3 Answers3

10

Use the onLoad event on your <img> element. You can give it a display: none style until it finishes loading.

class ImageRoll extends React.Component {
  state = {loaded: false};
  
  showImage = () => {
    this.setState({loaded: true});
  }
  
  render() {
    return (
      <>
        <img src="/path-to-initial" style={ this.state.loaded ? {display: "none"} : {}} />
        <img src="/path-to-seocndary" onLoad={this.showImage} style={ this.state.loaded ? {} : {display: "none"}} />
      </>
    );
  }
}

Edit: As opposed to the other answers, the reason we want to do this is that replacing the src on an image is actually bad practice. If you want to roll an image it is better to have two <img> elements and toggle between them depending on conditions.

Chase
  • 2,206
  • 1
  • 13
  • 17
3

As I understand the situation, you want to load the first image with the page then after the page has loaded, replace the first image with an image from another source.

In the example below the default image is "https://via.placeholder.com/100", it is displayed as the page loads. The second image is "https://via.placeholder.com/300", and is displayed after page load is complete.

Set up all image tags by adding the attribute data-src="secondimage.jpg" in the image tag.

How this works: After page load is complete, the script loops over all img tags checking for the data-src attribute. If an img tag has a data-src attribute it replaces the src image with the address in data-src attribute.

If you want to pre-load the external secondary images just add new Image().src = "secondimage.jpg"; to your script.

If you press Run code snippet you will see the image shows 300 indicating the second image has replaced the first default one. See the commented section below for pre-loading secondary images if desired.

/*
uncomment if you want to pre-load the secondary images
new Image().src = 'https://via.placeholder.com/300';
new Image().src = 'https://via.placeholder.com/400';
new Image().src = 'https://via.placeholder.com/500';
... as many as necessary
*/

window.onload = function() {
 imgs = document.querySelectorAll('img');
 for (i = 0; i < imgs.length; i++) {
  if (imgs[i].getAttribute('data-src')) {
   imgs[i].setAttribute('src', imgs[i].getAttribute('data-src'));
  }
 }
}
<img data-src="https://via.placeholder.com/300" src="https://via.placeholder.com/100">
Steve Lage
  • 692
  • 6
  • 11
  • Does this mean, that when it replaces the img's src it will only overwrite when it loads the second src of the imag fully? So I'll get rid of the few second blank space? – Laczkó Örs Sep 02 '19 at 14:19
  • I tested it just now online with a large data-src image and I did not get any blank time between the two images displaying. The first image displayed for a fraction of a second then the second larger image replaced it immediately without blank space. I tested it with Chrome. If a different browser gives a blank space while the second image loads you could try pre-loading it by adding new Image().src = "url-of-second-image.jpg"; to your script, like the commented section above shows. But try it first without the pre-load because it didn't show any blank space for me. – Steve Lage Sep 02 '19 at 18:52
1

You can just update directly the src of the image, I have a sample on Code Sandbox.

This is the content:

function App() {
  const [imageSrc, setImageSrc] = React.useState("/placeholder.jpg");

  function loadImage() {
    setImageSrc(`https://picsum.photos/200?${Date.now()}`);
  }

  return (
    <div className="App">
      <div>
        <img alt="small-image" src={imageSrc} />
      </div>
      <div>
        <button onClick={loadImage}>Load Image!</button>
      </div>
    </div>
  );
}

This is just a basic example, you can implement your own logic. Hope this helps!

Jojo Tutor
  • 810
  • 6
  • 7
  • Thank you! But how do I adjust the src change to when the picture does load? – Laczkó Örs Aug 30 '19 at 16:45
  • You mean, the src was already changed, but the image content is still loading, you want to have a fallback image? – Jojo Tutor Aug 30 '19 at 16:49
  • What I mean is that when the page loads it has an img and it uses it to fill up images with content. I want that when the real images have loaded thy overwrite the default. – Laczkó Örs Aug 30 '19 at 16:55
  • If I was not using a default image I would have a few (depending on the interconnection) seconds when the page is empty. This is what I want to avoid. – Laczkó Örs Aug 30 '19 at 16:56
  • You could not achieve that by using image on initial load, as you can see, when the page loads, it fetches the assets and even though you have a default image it still need to be loaded. What you can do is maybe implement some Skeleton, example: https://www.npmjs.com/package/react-loading-skeleton. By using this feature, you can combine it with https://www.npmjs.com/package/react-image as your loader. – Jojo Tutor Aug 30 '19 at 16:59
  • Can you explain what is this? :) – Laczkó Örs Aug 30 '19 at 17:02
  • Check the link, I have given some examples: https://codesandbox.io/s/keen-shamir-dgxxf – Jojo Tutor Aug 30 '19 at 17:02