How to obtain a URI for an image asset in React Native (With Expo)
By: Fernando De Freitas
Tags: Expo, JavaScript, React, React Native, Require

Now, the important bit:

React Native’s official Image Component provides us with a method called resolveAssetSource(). This method takes a “number” (related to what I’ve mentioned above) or an ImageSource object as its only parameter and returns an object with width , height , scale and uri properties, this last one being the one we care about in this case. This will look like:

const exampleImageUri = Image.resolveAssetSource(exampleImage).uri

Now, what’s the point of all this you ask. Well, to be honest you could always use require() and it would work and that’s it right? Well not exactly.

The problem with using require() for image assets

Using require() has a couple of caveats. First, it’s CommonJS and we’re working on the browser-side of things, where it doesn’t really belong, in the end you’re using just a synthetic require() being provided by the bundler.

Second, we’d have a mixture of ESModule import s and CommonJS require() in our codebase. Something we can easily avoid it, at least in this case.

Third, the second to most important in my opinion. The syntax is different when you want to display your image in an <Image> component.

require (CommonJS)

import { Image } from 'react-native'; const exampleImage = require('./assets/images/example.png') <Image source={exampleImage} />

import (ESModule)

import { Image } from 'react-native'; import exampleImage from ' ./assets/images/example.png ' const exampleImageUri = Image.resolveAssetSource(exampleImage).uri <Image source={{uri: exampleImageUri}} />

Bonus (Dynamic imports)

I know it’s also possible for require() , but you could even use dynamic imports, like:

import { Image } from 'react-native'; const {default: exampleImage } = await import(' ./assets/images/example.png ') const exampleImageUri = Image.resolveAssetSource(exampleImage).uri

And lastly, by using import you’ll provide the source attribute to the <Image/> component in the same format you’ll need to provide it when you eventually finish your POC and start working with real data, fetching images from external URLs like CDNs and the like, that source format is and object with a uri property, like:

{uri: exampleImageUri}

Conclusion

In conclusion, this way you have a consistent way of handling image assets. All the code and components you wrote to handle and display your images when getting started building your app will still be useful once you switch from dummy to real data from external sources. No need to refactor components and update source props and the like.

Anyways, I hope this is useful to you, I’m still trying to master React (Native), this post is one part note-taking for myself and one part writing it down so somebody having the same issues can find it. If something I’ve stated in this post is wrong feel free to leave a note and I’ll try to get it corrected.

A couple of things to know about the URI structure

This uri property is comprised of a normal looking URL, in the form of :

http://127.0.0.1:19001/assets/assets/images/examples.png?platform=<android|ios...>&hash=<asset_hash>?platform=<android|ios...>&dev=true&minify=false&hot=false

A couple of things worth noting:

There are two assets/ directories in the path, I’m assuming the top one relates to an internal directory for the bundler and the second one being part of the string path we’ve specified in our import statement example.

directories in the path, I’m assuming the top one relates to an internal directory for the bundler and the second one being part of the string path we’ve specified in our import statement example. For some reason it also has 2 sets of query strings. I’m assuming the second set being for the dev server and the first one some other internal Expo-related service.

Now I’m not sure how this URI translates in production but, according to the Assets Guide in Expo’s official documentation, Expo uploads the project’s assets to Amazon CloudFront and I’m assuming creates some kind of map/replaces all assets references with the CDN URLs internally.

References