How to pre-cache images used by react-navigation

With my expo app, the back navigation button images disappear when not connected to the internet. Is there some way I can pre-cache these images at startup using Asset.loadAsync ?

1 Like

hi there!

soon we will have asset bundling in standalone apps, but until then this is an important thing to consider for sure.

to do this, you can do the same thing as you would for an image in your project, but just point to the module in react-navigation: https://github.com/react-community/react-navigation/tree/master/src/views/assets

so Asset.fromModule(require('react-navigation/src/views/assets/back-icon.png')).downloadAsync() during your AppLoading process

Hi again @notbrent,

I’m using SDK 24, previoulsy I was using Asset.downloadAsync() to cache images, now I implemented assetBundlePatterns to include them in the bundle.

So I removed downloadAsync(), but things are not working as expected since there is a delay displaying the back-icon from react-navigation image.

Please see the following examples:

without Asset.downloadAsync()

with Asset.downloadAsync()

This is my app.json:

{
  "expo": {
    "name": "SkyApp",
    "description": "An empty new project",
    "slug": "skyapp",
    "privacy": "unlisted",
    "sdkVersion": "24.0.0",
    "version": "0.4.0",
    "orientation": "portrait",
    "primaryColor": "#cccccc",
    "icon": "./assets/icons/app-icon.png",
    "splash": {
      "image": "./assets/images/splash.png"
    },
    "packagerOpts": {
      "assetExts": ["ttf", "mp4"]
    },
    "ios": {
      "bundleIdentifier": "py.com.skycop.skyapp"
    },
    "android": {
      "package": "py.com.skycop.skyapp",
      "permissions": [ "ACCESS_COARSE_LOCATION", "ACCESS_FINE_LOCATION" ]
    },
    "assetBundlePatterns": [  
      "assets/**",
      "node_modules/react-navigation/src/**/*.png",
    ]
  }
}

Also I’m loading Expo with this command:

$ exp start --clear --tunnel --dev

BTW, Its not clear how assetBundlePatterns works internally, the cache routines should work together with this new flag? or i could remove this piece of code?

const cacheImages = (images) => {
  return images.map(image => {
    if (typeof image === 'string') {
      return Image.prefetch(image);
    } else {
      return Asset.fromModule(image).downloadAsync();
    }
  });
};

async _initAsync() {
  const imageAssets = cacheImages([
    require('./assets/images/logo.png'),
    require('./assets/icons/loading-icon.png'),
    require('react-navigation/src/views/assets/back-icon.png'),
  ]);
  const fontAssets = cacheFonts([MaterialIcons.font]);
  await Promise.all([ ...imageAssets, ...fontAssets ]).then(() => {
    if (__DEV__) {
      console.log('Application initialized');
    }
  });
}

Thanks !!!