Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show default element while loading Image

Tags:

react-native

I have a component representing an user avatar that loads an image from my API. I want it to display a default avatar (not another image) while the avatar is loading.

constructor() {
  super();
  this.state = {
    loaded: false,
  };
}

render() {
  if (!this.props.uri || !this.state.loaded) {
    return (
      <DefaultAvatar />
    );
  }
  return <Image onLoad={this.onLoad.bind(this)} uri={this.props.uri} />;
}

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

The problem I have is that with this current code, the Image will never be rendered, so the state will never change. I'm unable to find a solution that would satisfy React principles and my requirements (no ghost components to load the image before displaying it).

like image 857
Bhullnatik Avatar asked Feb 02 '16 19:02

Bhullnatik


3 Answers

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

  handleLoad () {
    this.setState({loaded:true})
  }

  componentDidMount () {
    this.img = new Image()
    this.img.onload = this.handleLoad.bind(this)
    this.img.src = this.props.src
  } 

  render () {
    return this.state.loaded?<img src={this.props.src}/>:<div>Loading...</div>
  }
}

You create a native Image element and wait for it to load. Then you render the image with react. The browser is smart and fetches it from the cache this time. Instant render!

See http://jsfiddle.net/4hq3y4ra/3/ for a demo.

like image 87
fl0cke Avatar answered Oct 18 '22 23:10

fl0cke


There are several ways this can be achieved, however to keep things simple, you can use a literal condition to toggle default avatar and the actual image.

constructor() {
  super();
  this.state = {
    loaded: false,
  };
}

onLoad(dataUri) {
if(dataUri !== undefined){
    this.setState({loaded: true});
  }

},

render() {

    return (
          <Image  onLoad={this.onLoad} uri={this.state.loaded ? this.props.uri : 'default-avatar'} />
       );

}
like image 2
otunba Avatar answered Oct 18 '22 23:10

otunba


Image.prefetch will allow me to do what I want, thanks to everyone.

like image 1
Bhullnatik Avatar answered Oct 18 '22 21:10

Bhullnatik