Search code examples
reactjsimagelag

img tag lags a bit, showing the old page image for a second or two, and then showing the new image in react


The page has a prev and next buttons that lets us to iterate through the pages, displaying the data in rows of cards containing a image. On click of next of prev button for first time the text fields display instantly, but the img tag lags a bit, showing the old page image for a second or two, and then showing the new image in react.

Any idea how I can prevent this? Or at least get the first image to disappear immediately?


Solution

  • Judging from the information that you presented, it is hard to share a solution, without us even seeing it. What I can suggest you is adding a loader to the image, so it brings you much better user experience. Try the following:

     class LoadableImage extends Component {
      state = {
        isLoaded: false,
      };
    
      render() {
        let { path, alt, onLoad, ...rest } = this.props;
        return (
          <div className='position-relative h-100'>
            <img
              className='img-fluid p-3'
              src={ path }
              alt={ alt }
              { ...rest }
              onLoad={ this.handleImageLoad }
            />
            { !this.state.isLoaded && (
              <div className="loader-container">
                <span className="loader text-center">
                  <div> Custom loader text or animation </div>
                </span>
              </div>
            )
            }
          </div>
        );
      }
    
      componentDidUpdate(prevProps, prevState, snapshot) {
        if (prevProps.path !== this.props.path) {
          this.setState({ isLoaded: false });
        }
      }
    
      /**
       * Handles the load of the image and executes any overriden onLoad functions if available.
       * @param {Event} e
       */
      handleImageLoad = (e) => {
        if (this.props.onLoad) {
          this.props.onLoad(e);
        }
        this.setState({
          isLoaded: true,
        });
      };
    }
    

    CSS:

    .loader-container {
      position: absolute;
      left: 0;
      top: 0;
      bottom: 0;
      right: 0;
      background: rgba(0, 0, 0, 0.4);
      animation: fadeIn 0.3s ease-out;
      z-index: 110;
      overflow: hidden;
    }
    
    
    .loader {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      color: #0083db;
    }
    

    I am using Bootstrap 4 dependencies, but if you don't, here are the classes bodies:

    .position-relative {
      position: relative!important;
    }
    
    .h-100 {
      height: 100%!important;
    }
    
    .img-fluid {
      max-width: 100%;
      height: auto;
    }
    

    Usage:

    <LoadableImage path={'/image/path'} alt='Alternative text' />
    

    You could also add custom parameters to the <img> tag. Feel free to make your custom loader design.