Naga Nandhini
Naga Nandhini

Reputation: 203

Show a react-placeholder skeleton until a image loaded completely in a page

I'm Beginner in react, i want to show a skeleton placeholder until a image loads completely in my page so I used react-placeholder library for skeleton loader and set the loaded state to false so the skeleton loader shows. I then change the loaded to true by setState it on onLoad function on img tag but my problem is the state is not changing so the skeleton loader shows infinitely thus hiding the image.

how to fix this? what i done wrong here? Someone please help me solve this.

import React from 'react';
import ReactPlaceholder from 'react-placeholder';

class Home extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loaded: false
    }
  }
  handleImageLoaded() {
    this.setState({ loaded: true });
  }
  render() {
    return ( 
    <React.Fragment>
      <ReactPlaceholder type = 'rect' ready = {this.state.loaded} style = {{height: 160}} >
        <div className = "imageHolder" >
          <img src ="http://someImage.png" alt = "" onLoad={this.handleImageLoaded.bind(this)} />
        </div> 
      </ReactPlaceholder> 
    
    </React.Fragment>
    )
  }
}

Upvotes: 18

Views: 32116

Answers (1)

Javier Brea
Javier Brea

Reputation: 1415

"react-placeholder" is not rendering the image until state.loaded is true, so the onLoad callback will never be executed.

You should take the control of rendering the placeholder and control the image visibility by yourself, and do not use the "react-placeholder" component as it requires a children node, which is not the best election for this case.

import React, { Fragment } from "react";
import ImagePlaceholder from "./ImagePlaceholder";

class Image extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loaded: false
    }
  }

  handleImageLoaded() {
    this.setState({ loaded: true });
  }

  render() {
    const { loaded } = this.state;
    const imageStyle = !loaded ? { display: "none" } : {};
    return ( 
      <div className = "imageHolder" >
        {!loaded && <ImagePlaceholder/> }
        <img src ="http://someImage.png" style={imageStyle} onLoad={this.handleImageLoaded.bind(this)} />
      </div>
    )
  }
}

Anyway, if you still want to continue using "react-placeholder", then you could solve it with something like:

import React, { Fragment } from "react";
import ReactPlaceholder from "react-placeholder";

class Image extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loaded: false
    }
  }

  handleImageLoaded() {
    this.setState({ loaded: true });
  }

  render() {
    const { loaded } = this.state;
    const imageStyle = !loaded ? { display: "none" } : {};
    const image = <img src="http://someImage.png" style={imageStyle} onLoad={this.handleImageLoaded.bind(this)} />;
    return (
      <Fragment>
        <ReactPlaceholder type="rect" ready={this.state.loaded} style={{height: 160}} >
          <div className="imageHolder" >
            {image}
          </div> 
        </ReactPlaceholder>
        {!loaded && image}
      </Fragment>
    )
  }
}

Upvotes: 23

Related Questions