Images rendered incorrectly on load

I am trying to insert a list of images into my webpage. I am able to successfully do this but I run into issues when displaying them on the page. I am using the react-grid-gallery package to display the images. In this package, you need to set the thumbnail height and width initially. This causes a problem for me because each image is a different height and width. What I want is to use Javascript to determine the height and width of each image and dynamically set them to the associated images.

I am not too familiar with React so I tried changing where I declared the size of the images. I set the image size in componentDidMount, constructor, etc. but nothing has been working.

constructor(props) {
    super(props);

    this.state = { stills: STILLS, val: 4 };

    this.setImgSize = this.setImgSize.bind(this);

    this.state.stills.map( (image, index) => {
      this.setImgSize(image, index);
    })
  }


setImgSize(image, index) {

    var newImg = new Image();

    newImg.onload = (function() {
      console.log("Onload");

      this.setState(state => {
        const stills = state.stills.map((still, id) => {
          if (id === index) {
            still.thumbnailHeight = newImg.height;
            still.thumbnailWidth = newImg.width;
          }
        })
      });
    }).bind(this);

    newImg.src = image.src; // this must be done AFTER setting onload
  }

The images are initially being displayed in the sizes that I set but after navigating away from the page and then navigating back to the page, the images are correct size.

1 answer

  • answered 2019-06-12 04:15 Meera

    React constructor is not the best place to perform an asynchronous operation.

    'onload' method is asynchronous - so one needs to wait until it returns back with the results. You could achieve the result by using Promise - and move the entire functionality in componentDidMount life cycle method.

    I modified the code from 'quick and dirty' example at react-grid-gallery to read image thumbnail width and height properties.

    setImgSize = (  image )=> {
        const promise = new Promise( function(resolve, reject) {
    
         let img = new Image();
         img.src = image.thumbnail;
         img.onload =  () => {
             // Should see width and height of images
             console.log( 'imge src', img.src, 'width ' , img.width, 'height', img.height);
             image.thumbnailHeight = img.height;
             image.thumbnailWidth = img.width;
             resolve('ok');               
              }
    
       });
       return promise;
    }
    
    
    
    componentDidMount() {
          Promise.all(this.IMAGES.map(this.setImgSize)).then(  (result) => { 
            //console.log('before state', result);
            this.setState({loading: false});
            console.log('after loop');
             }, function (error) {
                   console.log('error ', error);
           });
    
    }
    

    Here is the complete code in codesandbox: https://codesandbox.io/s/react-grid-gallery-ztf4n?fontsize=14