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).
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.
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'} />
);
}
Image.prefetch
will allow me to do what I want, thanks to everyone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With