Caching images in React Native

Rein Van Imschoot
React Native Training
4 min readApr 23, 2018

This article targets apps built with react-native init or ejected from the Expo SDK.

I can still recall the moment where I realised something was terribly wrong.
I was on the verge of publishing my first app. I had gone over everything and I felt I had my bases covered.

It was then I suddenly wondered how much data my app was actually consuming. Not that I was concerned. After all, it couldn’t be much. Some news headline images and some item thumbnails surely wouldn’t make a dent.

It turned out I was wrong. My seemingly innocent little app had already devoured hundreds of megabytes of data and it didn’t take long to find the culprit. The images were downloaded every time the app was launched, none of them were cached.

To give you an idea of what caching images can mean for your applications, I built an experiment that fetches ten image from Unsplash without any caching enabled. The average file size is 10 megabytes.

The example app using images from Unsplash.

This is the result of opening and closing the app five times.

The app downloads the images every time it launches, which is very much undesired and poor design.

Not only does this result in exponential data usage, which is an unpleasant surprise for your customers, it also makes your apps reliant on network connection every time external images are shown. This can either result in long loading times or no images at all.

To provide our apps with minimal data usage, faster reponse time and improved offline capabilities, let us take a look at how we can cache external images.

React Native Cache Control

When questing for functionality, it is worthwhile to see what React Native provides out-of-the-box before resorting to external packages.

Regarding image caching, however, it is a bit wanting. For a long time, React Native did not offer any image caching capabilities at all. They only recently added a Cache property to their image components, giving some control over the cache layer.

This is a quick example, as seen in the docs.

<Image
source={{
uri: 'https://facebook.github.io/react/logo-og.png',
cache: 'only-if-cached',
}}
style={{width: 400, height: 400}}
/>

The big caveat here is that, at the time of writing, cache-control is supported only for iOS. On top of that, it does not always work as it should, providing a less-than-optimal solution.

React-native-cached-image

A better alternative, in my opinion, is a package called react-native-cached-image by Kfir Golan.

React-native-cached-image provides a CachedImage component that serves as a drop-in replacement for Image and ImageBackground. Should the need arise, you can also use ImageCacheManager for more fine-grained cache control.

Before we can use this package, however, we must first add react-native-fetch-blob on which react-native-cached-image relies for its file system access.

Installing react-native-fetch-blob

Add and link the package. No other configuration is needed, since this package is mainly used under the hood.

yarn add react-native-fetch-blob
react-native link react-native-fetch-blob

If you have a non-default project structure, automatic linking might not work. In that case, detailed instructions for manual linking are provided in the project’s wiki.

Installing react-native-cached-image

When react-native-fetch-blob is installed, adding react-native-cached-image is simply a matter of adding it to your project.

yarn add react-native-cached-image

Using react-native-cached-image

When both packages are successfully installed, you can import CachedImage and replace any instances of Image or ImageBackground that you want cached.

import { CachedImage } from 'react-native-cached-image';

In my example app, I set up a FlatList to show the images. The renderItem implementation can thus be changed.

<CachedImage 
style={{
width: Dimensions.get('screen').width,
height: Dimensions.get('screen').width,
}}
source={{ uri: item.urls.raw }}
/>

When this was done, I repeated the previous experiment and opened and closed the example app five times. This was the result.

As you can see, the images are downloaded once and subsequently fetched from cache. This has the added benefit of not having to deal with slow and unpredictable networks, thus giving you app faster response times and better offline support.

--

--