138

I'm currently building a test app using React Native. The Image module thus far has been working fine.

For example, if I had an image named avatar, the below code snippet works fine.

<Image source={require('image!avatar')} />

But if I change it to a dynamic string, I get

<Image source={require('image!' + 'avatar')} />

I get the error:

Requiring unknown module "image!avatar". If you are sure the module is there, try restarting the packager.

Obviously, this is a contrived example, but dynamic image names are important. Does React Native not support dynamic image names?

React native error with dynamic image name

Shaheen Ghiassy
  • 7,397
  • 3
  • 40
  • 40
  • 1
    I encountered similar problem with Vue, answer is here https://stackoverflow.com/questions/40491506/vue-js-dynamic-images-not-working/60970936#60970936 – Alonad Apr 01 '20 at 12:36

16 Answers16

104

This is covered in the documentation under the section "Static Resources":

The only allowed way to refer to an image in the bundle is to literally write require('image!name-of-the-asset') in the source.

// GOOD
<Image source={require('image!my-icon')} />

// BAD
var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive';
<Image source={require('image!' + icon)} />

// GOOD
var icon = this.props.active ? require('image!my-icon-active') : require('image!my-icon-inactive');
<Image source={icon} />

However you also need to remember to add your images to an xcassets bundle in your app in Xcode, though it seems from your comment you've done that already.

http://facebook.github.io/react-native/docs/image.html#adding-static-resources-to-your-app-using-images-xcassets

Vincent Orback
  • 2,327
  • 22
  • 35
Colin Ramsay
  • 16,086
  • 9
  • 52
  • 57
86

RELEVANT IF YOU HAVE KNOWN IMAGES (URLS):

The way I hacked my way through this problem:

I created a file with an object that stored the image and the name of the image:

export const ANIMAL_IMAGES = {
  dog: {
    imgName: 'Dog', 
    uri: require('path/to/local/image')
  },
  cat: {
    imgName: 'Cat on a Boat', 
    uri: require('path/to/local/image')
  }
}

Then I imported the object into the component where I want to use it and just do my conditional rendering like so:

import { ANIMAL_IMAGES } from 'path/to/images/object';

let imgSource = null;

if (condition === 'cat') {
  imgSource = ANIMAL_IMAGES.cat.uri;
}

<Image source={imgSource} />

I know it is not the most efficient way but it is definitely a workaround.

Hope it helps!

Walter Monecke
  • 2,386
  • 1
  • 19
  • 52
81

This worked for me :

I made a custom image component which takes in a boolean to check if the image is from web or is being passed from a local folder.

// In index.ios.js after importing the component
<CustomImage fromWeb={false} imageName={require('./images/logo.png')}/>

// In CustomImage.js which is my image component
<Image style={styles.image} source={this.props.imageName} />

If you see the code, instead of using one of these:

// NOTE: Neither of these will work
source={require('../images/'+imageName)} 
var imageName = require('../images/'+imageName)

I'm just sending the entire require('./images/logo.png') as a prop. It works!

BK7
  • 1,161
  • 9
  • 15
  • 8
    This answer deserves more credit. It absolutely works when you declare the require statement and pass as a prop. Thank you so much for your simple explanation, I only wish others would be as clear. – dazziola Feb 23 '17 at 23:56
  • 1
    The prop thing work wonders. That should be stated on the official docs. – dasmikko Mar 03 '17 at 19:25
  • 1
    ```class CustomImage extends Component { constructor(props) { super(props); } render() { return ( ); } }``` `````` – Pablo Jul 17 '17 at 14:55
  • 2
    In the parent Component I have `` and this in the child component `class CustomImage extends Component { constructor(props) { super(props); } render() { return ( ); } }` – Walter Monecke Jul 29 '17 at 13:16
  • Do I still have to add the images to xCode? – Walter Monecke Jul 29 '17 at 13:18
  • @BK7 It seems that i works for you because you hardcoded the URL in the CustomImage tag. However, mine is dynamic. – Walter Monecke Jul 29 '17 at 13:27
  • @WalterMonecke I think you're right, I just checked for dynamic URLs, it's not working. You need not add images separately to Xcode as react-native link will take care of it. – BK7 Jul 31 '17 at 12:27
  • Hi, dear @BK7 I tried your answer and it didn't work [check this](https://pastebin.com/BYSh6mkw), what did I missing? could you help with a check? have been stuck here :D – armnotstrong Aug 23 '17 at 03:23
  • Hi @armnotstrong, It doesn't work because you're passing a variable to the require method, i.e require(item). unfortunately, it works only if you pass hardcoded urls i.e the string as quoted in the above example. Still couldn't figure out why that happens. I'd recommend you upload these files in AWS S3 or firebase hosting etc.. and use the uri method of getting images instead. – BK7 Aug 23 '17 at 08:53
  • @BK7 thanks for replying that, and I have chosen to input all those file paths with my bare hand, this is insane and hope reactnative could fix that :-( – armnotstrong Aug 23 '17 at 09:30
  • @armnotstrong Hopefully. – BK7 Aug 23 '17 at 11:08
  • 3
    Pure genius, this is exactly what I was searching for :) – Sumit Sahoo Jan 20 '19 at 16:06
  • 1
    this doesn't help me with the problem of not being able to use concatenated strings in the "require" – Zack Aug 07 '19 at 17:45
  • 1
    This should be the preferred answer – jsog Jan 19 '21 at 19:20
  • 1
    I have been trying to solve this problem for a long time. Thank you very much this method works – Hasan Basri May 22 '22 at 21:50
47

If you're looking for a way to create a list by looping through a JSON array of your images and descriptions for example, this will work for you.

  1. Create a file (to hold our JSON database) e.g ProfilesDB.js:

const Profiles = [
  {
    id: '1',
    name: 'Peter Parker',
    src: require('../images/user1.png'),
    age: '70',
  },
  {
    id: '2',
    name: 'Barack Obama',
    src: require('../images/user2.png'),
    age: '19',
  },
  {
    id: '3',
    name: 'Hilary Clinton',
    src: require('../images/user3.png'),
    age: '50',
  },
];

export default Profiles;
  1. Then import the data in our component and loop through the list using a FlatList:

import Profiles from './ProfilesDB.js';

<FlatList
  data={Profiles}
  keyExtractor={(item, index) => item.id}
  renderItem={({item}) => (
    <View>
      <Image source={item.src} />
      <Text>{item.name}</Text>
    </View>
  )}
/>

Good luck!

Moso Akinyemi
  • 715
  • 6
  • 14
  • This is exactly what I was looking for. I am creating a local "data" file in my app and I needed to access the images. I have tried But it was not working so after trying the solution you provided it worked for me. Thank you! – Denis Denchev Jun 06 '21 at 22:07
  • 1
    if there is more image files then what would be the logic to achive that? I can't write code manually for all those 50 images. I was able to list out all images and export all but it was node js code. – CrackerKSR Nov 17 '21 at 11:12
  • @CrackerKSR, you're right. This solution usually works best for a few images. – Moso Akinyemi Nov 28 '21 at 09:49
20

As the React Native Documentation says, all your images sources needs to be loaded before compiling your bundle

So another way you can use dynamic images it's using a switch statement. Let's say you want to display a different avatar for a different character, you can do something like this:

class App extends Component {
  state = { avatar: "" }

  get avatarImage() {
    switch (this.state.avatar) {
      case "spiderman":
        return require('./spiderman.png');
      case "batman":
        return require('./batman.png');
      case "hulk":
        return require('./hulk.png');
      default:
        return require('./no-image.png');
    }
  }

  render() {
    return <Image source={this.avatarImage} />
  }
}

Check the snack: https://snack.expo.io/@abranhe/dynamic-images

Also, remember if your image it's online you don't have any problems, you can do:

let superhero = "spiderman";

<Image source={{ uri: `https://some-website.online/${superhero}.png` }} />
Abraham
  • 8,525
  • 5
  • 47
  • 53
20

First, create a file with image required - React native images must be loaded this way.

assets/index.js

export const friendsandfoe = require('./friends-and-foe.png'); 
export const lifeanddeath = require('./life-and-death.png'); 
export const homeandgarden = require('./home-and-garden.png');

Now import all your assets

App.js

import * as All  from '../../assets';

You can now use your image as an interpolated value where imageValue (coming in from backend) is the same as named local file ie: 'homeandgarden':

<Image style={styles.image} source={All[`${imageValue}`]}></Image>
HannahCarney
  • 3,441
  • 2
  • 26
  • 32
11

Important Part here: We cannot concat the image name inside the require like [require('item'+vairable+'.png')]

Step 1: We create a ImageCollection.js file with the following collection of image properties

ImageCollection.js
================================
export default images={
    "1": require("./item1.png"),
    "2": require("./item2.png"),
    "3": require("./item3.png"),
    "4": require("./item4.png"),
    "5": require("./item5.png")
}

Step 2: Import image in your app and manipulate as necessary

class ListRepoApp extends Component {

    renderItem = ({item }) => (
        <View style={styles.item}>
            <Text>Item number :{item}</Text>
            <Image source={Images[item]}/>
        </View>
    );

    render () {
        const data = ["1","2","3","4","5"]
        return (
            <FlatList data={data} renderItem={this.renderItem}/>
        )
    }
}

export default ListRepoApp;

If you want a detailed explanation you could follow the link below Visit https://www.thelearninguy.com/react-native-require-image-using-dynamic-names

Courtesy : https://www.thelearninguy.com

5

you can use

<Image source={{uri: 'imagename'}} style={{width: 40, height: 40}} />

to show image.

from:

https://facebook.github.io/react-native/docs/images.html#images-from-hybrid-app-s-resources

SamYang
  • 59
  • 1
  • 2
5
import React, { Component } from 'react';
import { Image } from 'react-native';

class Images extends Component {
  constructor(props) {
    super(props);
    this.state = {
           images: {
                './assets/RetailerLogo/1.jpg': require('../../../assets/RetailerLogo/1.jpg'),
                './assets/RetailerLogo/2.jpg': require('../../../assets/RetailerLogo/2.jpg'),
                './assets/RetailerLogo/3.jpg': require('../../../assets/RetailerLogo/3.jpg')
            }
    }
  }

  render() {
    const {  images } = this.state 
    return (
      <View>
        <Image
                            resizeMode="contain"
                            source={ images['assets/RetailerLogo/1.jpg'] }
                            style={styles.itemImg}
                        />
     </View>
  )}
}
Zhong Ri
  • 2,556
  • 1
  • 19
  • 23
4

To dynamic image using require

this.state={
       //defualt image
       newimage: require('../../../src/assets/group/kids_room3.png'),
       randomImages=[
         {
            image:require('../../../src/assets/group/kids_room1.png')
          },
         {
            image:require('../../../src/assets/group/kids_room2.png')
          }
        ,
         {
            image:require('../../../src/assets/group/kids_room3.png')
          }
        
        
        ]

}

when press the button-(i select image random number betwenn 0-2))

let setImage=>(){
//set new dynamic image 
this.setState({newimage:this.state.randomImages[Math.floor(Math.random() * 3)];
})
}

view

<Image
        style={{  width: 30, height: 30 ,zIndex: 500 }}
        
        source={this.state.newimage}
      />
Balaji
  • 9,657
  • 5
  • 47
  • 47
2

I know this is old but I'm going to add this here as I've found this question, whilst searching for a solution. The docs allow for a uri: 'Network Image'

https://facebook.github.io/react-native/docs/images#network-images

For me I got images working dynamically with this

<Image source={{uri: image}} />
DaveClissold
  • 59
  • 1
  • 6
2
 <StyledInput text="NAME" imgUri={require('../assets/userIcon.png')} ></StyledInput> 

<Image
            source={this.props.imgUri}
            style={{
              height: 30,
              width: 30,
              resizeMode: 'contain',
            }}
          />   

in my case i tried so much but finally it work StyledInput component name image inside the StyledInput if you still not understand let me know

Naved Khan
  • 1,699
  • 16
  • 13
2

Say if you have an application that has similar functionality as that of mine. Where your app is mostly offline and you want to render the Images one after the other. Then below is the approach that worked for me in React Native version 0.60.

  1. First create a folder named Resources/Images and place all your images there.
  2. Now create a file named Index.js (at Resources/Images) which is responsible for Indexing all the images in the Resources/Images folder.

const Images = { 'image1': require('./1.png'), 'image2': require('./2.png'), 'image3': require('./3.png') }

  1. Now create a Component named ImageView in your choice of folder. One can create functional, class or constant component. I have used the Const component. This file is responsible for returning the Image depending on the Index.
import React from 'react';
import { Image, Dimensions } from 'react-native';
import Images from './Index';
const ImageView = ({ index }) => {
    return (
        <Image
            source={Images['image' + index]}
        />
    )
}
export default ImageView;
  1. Now from the component wherever you want to render the Static Images dynamically, just use the ImageView component and pass the index.

    < ImageView index={this.qno + 1} />

Vasanth
  • 560
  • 1
  • 5
  • 25
1

Create a constant where you save the image path including require, then in source put the name of that constant.

const image = condition ? require("../img/image1.png") : require('../img/image2.png');

<Image source={image} />
Vladimir Salguero
  • 5,609
  • 3
  • 42
  • 47
1

Here is a simple and truly dynamic solution to the problem if you have a bigger no of files.

-Won't work for Expo Managed

Although the question is old I think this is the simpler solution and might be helpful. But I beg a pardon for any terminological mistakes, correct me please if I do any.

INSTEAD OF USING REQUIRE WE CAN USE THE URI WITH NATIVE APP ASSETS FOR ANDROID (AND/OR iOS). HERE WE WILL DISCUSS ABOUT ANDROID ONLY

URI can easily be manipulated as per the requirement but normally it's used for network/remote assets only but works for local and native assets too. Whereas require can not be used for dynamic file names and dirs

STEPS

  1. Open android/app/src/main/assets folder from your App.js or index.js containing directory, if the assets folder doesn't exist create one.
  2. Make a folder named images or any NAME of your choice inside assets, and paste all the images there.
  3. Create a file named react-native.config.js in the main app folder containing App.js or index.js.
  4. Add these lines to the new js file:

module.exports = {
  project: {
    ios: {},
    android: {},
  },
  assets: ['./assets/YOUR_FOLDER_NAME/'],
};

at the place of YOUR_FOLDER_NAME use the newly created folder's name images or any given NAME

  1. Now run npx react-native link in your terminal from main app folder, this will link/add the assets folder in the android bundle. Then rebuild the debug app.
  2. From now on you can access all the files from inside android/app/src/main/assets in your react-native app. For example:
<Image
   style={styles.ImageStyle}
   source={{ uri: 'asset:/YOUR_FOLDER_NAME/img' + Math.floor(Math.random() * 100) + '.png' }}
/>
piedpipr
  • 155
  • 2
  • 7
-1

You should use an object for that.

For example, let's say that I've made an AJAX request to an API and it returns an image link that I'll save to state as imageLink:

source={{uri: this.state.imageLink}}

Richard Kho
  • 5,086
  • 4
  • 21
  • 35
  • 3
    for dynamic image path links, this doesn't work: `var img = "../img/icons/"+img_name+"_selected.png";
    `
    – Robert Tomas G IV May 27 '16 at 18:07
  • 4
    a hack for this, if you know all the img_name variants would be to go this way: `var images = { 'first': require('../first.png'), 'second': require('../second.png') } ` – Gabriel Lupu Nov 27 '16 at 19:02
  • 2
    Please be warned that for @GabrielLupu 's suggestion: You are allocating all of the images in the memory by this way. It depends on the number of images and their sizes however you will likely experience out of memory errors. – Lashae Apr 13 '17 at 10:38