Search code examples
javascriptreactjsreact-nativecreate-react-native-app

React Native: How to make modular components using local image and data assets?


create-react-native-app v1.0.0
react-native-cli 2.0.1
react-native 0.52.0
Android API 25

I have several JSON files in ./src/data (aliased as data) and images in ./src/assets/images (aliased as images).

I am making a list of images that are filterable and sortable based on the corresponding data. Additionally, I have different types of images the user can toggle between for compact and expanded view.

From my searching it looks like my plan to reference the image path dynamically from a data object property is not possible and I need to do something like:

import image1 from 'images/'image1.png';
import image2 from 'images/'image2.png';
<Image source={some_expression ? image1 : image2} />

or

<Image source={some_expression ? 
   require('images/image1.png') : require('images/image2.png')} />

That works for the toggle, but I still have the original problem where I can't actually assign image1 and image2 from my data objects such as:

var image1 = "images/" + data.image1.img

where data.image1.img is the filename.

Is there a way around this where I can dynamically reference the local images for the corresponding data in a reusable component?

Short of hardcoding individual components with the images for each data object, I'm at a loss.

I'm new to React and mobile in general so I may have overlooked something in the documentation or online searching.


Solution

  • For anyone with the same issue, here is what I did in order to use a string from my JSON data to reference the corresponding image to change what is shown dynamically.

    In Images.js import all static images:

    const images = {
      img1: require('images/img1.png'),
      imgNth: require('images/imgNth.png')
    }
    
    export default images;
    

    or alternatively

    import _img1 from 'images/img1.png';
    import _imgNth from 'images/imgNth.png';
    
    const images = {
      img1: _img1,
      imgNth: _imgNth
    }
    
    export default images;
    

    Then where you want to use them i.e. App.js:

    import images from 'images/Images';
    import data from 'data/Data';
    
    <Image source = {images[data[index].imgName]} />
    

    Where imgName is a property that contains the exact same string value as one of the properties in the imported images i.e. img1 or imgNth in this example.

    Regardless of how many images you have, I would suggest writing a simple script to run through your image folder and auto-generate an Images.js type file. It isn't hard to do and will save you a lot of work, especially if you add or remove images regularly during development so you don't have to manually update it each time.