Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Could Not Find Image File in React Native

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?

like image 360
JeffB6688 Avatar asked Sep 14 '25 00:09

JeffB6688


1 Answers

Using images with 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';

Using images on the device

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'

What's happening in your situation

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.

Snack

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');
like image 187
Andrew Avatar answered Sep 15 '25 21:09

Andrew