0

Under my "img" folder I have 5 folders: ("America", "Europe", "Asia", "Africa", "Australia"). Each of these folders contains several city images (Europe folder will hold London.jpg, Paris.jpg, Rome.jpg etc... for example)

Now, my reducer returns me 2 props. One represent the continent, and the other a city that belongs to the continent held in the previous prop.

What I want to achieve is to dinamically load the city image.

something like this:

var icon = (this.props.myContinent && this.props.myCity) ? 
      require('./img/'+{this.props.myContinent}+'/'+{this.props.myCity}+'.png');

<Image source={icon} />

I read this and this and they gave me an idea. But I'm still unable to solve this.

Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
splunk
  • 6,435
  • 17
  • 58
  • 105

3 Answers3

2

You can create icon component with object of paths to images and then in container just put city name to kind prop.

const paths = {
  'paris': require('./img/europe/paris.png'),
  'london': require('./img/europe/london.png'),
}


export default function Icon({ kind }) {
  return (
    <Image
      source={paths[kind]}
    />
  );
}

Then in container something like

<Icon kind={this.props.city} />
1

Your code is not working because the image name in require has to be known statically. According to the docs:

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

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

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

While this is a bit inconvenient, it is fairly easy to implement. In your case, I would to the following:

const images = {
    america: {
        caracas: require('images/america/caracas.png'),
        newyork: require('images/america/newyork.png')
    },
    europe:{
        london: require('images/america/london.png'),
        paris: require('images/america/paris.png')
        rome: require('images/america/rome.png')
    },
    asia:{
        // And so on...
    }
}

Then, your icon initialization should look like this:

var icon = (this.props.myContinent && this.props.myCity) ? images[this.props.myContinent][this.props.myCity] : null;

And in render you can do something like this. The '&&' mechanism is simply there to check if icon is null:

{icon && <Image source={icon} />}
martinarroyo
  • 9,389
  • 3
  • 38
  • 75
  • That's a bit inconvenient, I have hundreds of cities. But it works – splunk Jan 04 '17 at 13:05
  • I agree with you, if you have a lot of images it is a bit of a pain. Maybe you can automate the creation of the `images` object using a node script that recursively searches for image files and outputs the object. – martinarroyo Jan 04 '17 at 14:03
0

Issue is you are not using ternary condition properly. You are using ? without :. use some image when condition fails.

Write it like this:

var icon = (this.props.myContinent && this.props.myCity) ? 
    require(`./img/${this.props.myContinent}/${this.props.myCity}.png`) 
  : require('./img/defaultImage.png');

<Image source={icon}/>
Mayank Shukla
  • 100,735
  • 18
  • 158
  • 142
  • I get this error: Requiring unknown module "./img/Europe/London.jpg". If you are sure the module is there, try restarting the packager or running "npm install". – splunk Jan 04 '17 at 10:29
  • i think, its not able to find out the image, check your folder structure. – Mayank Shukla Jan 04 '17 at 10:45
  • I tried with: require('./img/Europe/London.jpg') and it shows the image then I tried with require('./img/'+this.props.myContinent+'/London.jpg') and it gives: Requiring unknown module "./img/Europe/London.jpg". If you are sure the module is there.... – splunk Jan 04 '17 at 11:09