I have defined a React Native class that is designed to fill a "tableView" cell with an image reference that is a prop input to the class. This is invoked with the use of FlatList. However, this class is unable to find the input image reference in the bundle when specified using an Image source tag. It can only be found if it is a hard coded reference.
The class is defined as follows:
class ListItem extends React.PureComponent {
_onPress = () => {
this.props.onPressItem(this.props.index);
}
render() {
const item = this.props.item;
console.log("ChannelSelection Mix Button artwork: ", item.artwork);
return (
<TouchableHighlight
onPress={this._onPress}
underlayColor="transparent">
<View>
<View style={styles.rowContainer}>
<Image source={{ uri: item.artwork }} style={styles.buttonContainer} />
<View style={styles.mixButtonTitleContainer}>
<Text style={styles.mixButtonTitle}
numberOfLines={2}>{item.channelTitle}</Text>
</View>
</View>
</View>
</TouchableHighlight>
);
}
}
When this class in invoked, I get a warning that says:
Warning
Could not find image file:///Users/myname/Library/Developer/CoreSimulator/Devices/34AE8A68-E69D-4804-B3C4-96DE7A051B9B/data/Containers/Bundle/Application/C79368E9-3D1B-492C-B72B-9BF5C4D3262B/myApp.app/./Resources/MissingAlbumArt.png
The console output to print item.artwork is:
'ChannelSelection Mix Button artwork: ', './Resources/MissingAlbumArt.png'
so you can see that the name of the file is being passed in correctly.
Note that if I change the line:
<Image source={{ uri: item.artwork }} style={styles.buttonContainer} />
to:
<Image source={require('./Resources/MissingAlbumArt.png')} style={styles.buttonContainer} />
then the error goes away.
So, how can I properly reference the .png files in my Resources directory? And why are my .png files not in the Resources directory of my bundle?
require
One way of using images is in the bundle. You access these images by using
const imageName = require('./path/to/the/image/imageName.png');
For images that I add this way I actually create a file (called Images.js
) that contains all of my requires and then exports the images. So in the file it would be a list of requires like this
export const imageName = require('./path/to/the/image/imageName.png');
Then when I want to use the image I import the image like so:
import { imageName } from '.path/to/Images.js';
Another way is to download the file and then save it in the documents directory of the application. Usually you use rn-fetch-blob
or react-native-fs
to download and save the file to a location, like the documents directory.
You would then construct the the path to the file and use that. So for example, if you were using react-native-fs
you could construct the path in the following way,
let pathToImage = RNFS.DocumentDirectoryPath + '/path/to/dowloaded/file/imageName.png'
You are mixing the two methods up. The images haven't been stored on your device when you are working in development. They are currently served to the device by the bundler. That way you have to use the require
method to access them. They get copied across when you use them (look at the logs in your bundler and you will see it happening).
When you create your production ipa
or apk
all the images and code get bundled together and added to the app, the require
statements tell the device where to find the images in that bundle. If you were to try to use the path of the file after it has been bundled into an ipa
or apk
it wouldn't work in development and you would end up with a similar error.
If you try to access the file using a path similar to the one below, it won't work as that file isn't there because the file is in the bundle. It is best to use the require
method.
file:///Users/myname/Library/Developer/CoreSimulator/Devices/34AE8A68-E69D-4804-B3C4-96DE7A051B9B/data/Containers/Bundle/Application/C79368E9-3D1B-492C-B72B-9BF5C4D3262B/myApp.app/./Resources/MissingAlbumArt.png
One thing to also note is that iOS
cannot guarantee that paths to files will remain static. If you run react-native run-ios
although the application is reloaded and only one application appears on device, it can actually move folders so it is always best to dynamically construct links to files that you have saved to any directory on iOS
.
Here is a snack that shows using Images.js
to store all the require for the files. https://snack.expo.io/@andypandy/requiring-images
Here is the directory structure that I have in this project
├── App.js
├── Images.js
├── README.md
├── app.json
├── assets
│ ├── bart.png
│ ├── lisa.png
│ ├── maggie.png
│ └── parents
│ ├── homer.jpg
│ └── marge.jpg
├── components
│ ├── AssetExample.js
│ └── SecondAssetExample.js
└── package.json
Here is how I am constructing the require
statements in the Images.js
export const MARGE = require('./assets/parents/marge.jpg');
export const HOMER = require('./assets/parents/homer.jpg');
export const BART = require('./assets/bart.png');
export const MAGGIE = require('./assets/maggie.png');
export const LISA = require('./assets/lisa.png');
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