Adding image placeholders in react native the right way

Saurabh Mhatre
CodeClassifiers
Published in
3 min readFeb 14, 2017
Image source:Pixabay

When developing applications in react native we often use image element which load images from some url. On faster networks and simple applications the images load gracefully and we generally don’t need to add image placeholders. However on slower connections andlike news,media and ecommerce applications which have long image grids or multiple image containers in scrollviews it becomes imperative to add image placeholders until the image is loaded in the app from url.

My first preferred approach was to defaultSource property available in Image element in react native.However it is currently available in ios and my app is mainly focused towards android community so that was out of question. I found one npm module which added defaultSource support to android but it did not work properly in my case. Finally I stumbled across an article which explained creation of custom placeholder component in ES5 syntax and converted the code to es6 without much efforts. Without boring you further with the background story lets start coding:

First we will add a small delay to loading of image using animated api to give the user a fading effect while image is rendered.Create a progressiveImage.js within folder where you keep your reusable components:

import React, { Component, PropTypes } from 'react';
import {
Animated,
View,
Image
} from 'react-native';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
class progressiveImage extends Component{
constructor(props){
super(props);
this.state = {
opacity: new Animated.Value(0)
}
}
onLoad(){
Animated.timing(this.state.opacity,{
toValue: 0,
duration : 250
}).start()
}
render(){
return (
<View
width={this.props.style.width}
height={this.props.style.height}
backgroundColor={'#ffffff'}
>
<Animated.Image
resizeMode = {'contain'}
key = {this.props.key}
style = {[
{
opacity: this.state.opacity
},
this.props.style
]}
source = {this.props.source}
onLoad = {(event)=>this.onLoad(event)}
/>
</View>
)
}
}
function mapStateToProps(state, ownProps) {
return {
};
}
function mapDispatchToProps(dispatch) {
return {
};
}
export default connect(mapStateToProps, mapDispatchToProps)(progressiveImage);

I am using redux in my project and you can simply export the class without using redux functions.Use the image component in your app as follows:

import ProgressiveImage from '../global/progressiveImage';...
class QAPage extends Component {
render(){
...
<ProgressiveImage source={{uri: stories.imageurl}} style={{width:viewportWidth,height:200}} key={"pimg"}/>
}
}

Now let us modify progressiveImage component to add placeholder view which gets replaced by image once it loaded through url:

class progressiveImage extends Component{
constructor(props){
super(props);
this.state = {
thumbnailOpacity: new Animated.Value(0)
}
}
onLoad(){
Animated.timing(this.state.thumbnailOpacity,{
toValue: 0,
duration : 250
}).start()

}
onThumbnailLoad(){
Animated.timing(this.state.thumbnailOpacity,{
toValue: 1,
duration: 250
}).start();
}
render(){
return (
<View
width={this.props.style.width}
height={this.props.style.height}
backgroundColor={'#ffffff'}
>
<Animated.Image
resizeMode = {'contain'}
key = {this.props.key}
style = {[
{
position: 'absolute'
},
this.props.style
]}
source = {this.props.source}
onLoad = {(event)=>this.onLoad(event)}
/>
<Animated.Image
resizeMode={'contain'}
key={this.props.key}
style={[
{
opacity: this.state.thumbnailOpacity
},
this.props.style
]}
source={this.props.thumbnail}
onLoad={(event) => this.onThumbnailLoad(event)}
/>
</View>
)
}
}

Add thumbnail property to your implementation as follows:

<ProgressiveImage source={{uri: stories.imageurl}} thumbnail={require("../../images/placeholder.png")} style={{width:viewportWidth,height:200}} key={"pimg"}/>

I would recommend keeping the placeholder/thumbnail image in the app itself for loading it even when app is offline so that user at least sees placeholder image instead of a blank view.

That’s it for today’s tutorial. You can read the original article from which this tutorial is heavily borrowed here. If anyone is interested in creating a better npm module out of this or know about one already then feel free to mention it in the comments section or ping me on facebook or medium.

Connect Deeper:

You can follow our facebook page to get notified about similar such articles in the future: Technoetics or simply follow me back on medium.

--

--

Saurabh Mhatre
CodeClassifiers

Senior Frontend Developer with 9+ years industry experience. Content creator on Youtube and Medium. LinkedIn/Twitter/Instagram: @SaurabhNative