React Native - Dynamic Image Source

2020-08-25 05:56发布

问题:

I'm trying to loop through the SOURCE array with the map method, but I keep getting this error:

Unknown named module: '../images/one.jpeg'

Anyone know why this is happening? The file path in the require is definitely correct.

var SECTIONS = [
  {
    title: 'One',
    fileName: 'one.jpeg',
  },
  {
    title: 'Two',
    fileName: 'two.jpeg',
  },
  {
    title: 'Three',
    fileName: 'three.jpeg',
  },
  {
    title: 'Four',
    fileName: 'four.jpeg',
  },
];


{SECTIONS.map((section, i) => (
   <CategoryCard
     key={i}
     source={require(`../images/${section.fileName}`)}
     title={section.title}
   />
))}

回答1:

I don't think this is possible because react native needs to know what to bundle ahead of time (AFAIK). However, you can require all the files in your array:

var SECTIONS = [
  {
    title: 'One',
    file: require('../images/one.jpeg'),
  },
  {
    title: 'Two',
    file: require('../images/two.jpeg'),
  },
  {
    title: 'Three',
    file: require('../images/three.jpeg'),
  },
  {
    title: 'Four',
    file: require('../images/four.jpeg'),
  },
];


{SECTIONS.map((section, i) => (
   <CategoryCard
     key={i}
     source={section.file}
     title={section.title}
   />
))}


回答2:

You can't use dynamic links. The best hack that i found to solve this is this:

var SECTIONS = {
  One: {
    title: 'One',
    file: require('../images/one.jpeg'),
  },
  Two: {
    title: 'Two',
    file: require('../images/two.jpeg'),
  },
  Three: {
    title: 'Three',
    file: require('../images/three.jpeg'),
  },
  Four: {
    title: 'Four',
    file: require('../images/four.jpeg'),
  },
};


{SECTIONS.map((section, i) => (
   <CategoryCard
     key={i}
     source={section.file}
     title={section.title}
   />
))}

That way, you can just use the files and if you have some kind of dynamic image selection, you can just use something like this

<Image source={SECTIONS[image.type]} />


回答3:

try opening the file in separate browser using direct URL something like

http://<><>/imgages/one.jpg

You can also do something like this as well:

One working example for displaying dynamic images using react :

Example Click Here



回答4:

Got a working solution, though not recommended for large images, works perfectly for (a lot of)small images.

Steps:

  1. Convert the icon(s) to base64 string(s).
  2. Create a JSON file with filename as the keys and the base64 strings as values. (You can also store them to a local database)

e.g. ImageData.json

{

"icon1": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQ.......==",
"icon2": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQ.......=="

}

3.Import the json file to the place where you require the images dynamically.

e.g.

const imageData = require("./images/ImageData.json")

4: Get/generate the key/filename at runtime. and get the image source.

e.g.

const imageSrc = imageData[keyname]

5: Generate a image dynamically at runtime.

e.g.

<Image style={{ width: 70, height: 70, resizeMode: Image.resizeMode.contain }} source={ uri: imageSrc } />

Done..

Extra.. Written a helper python script to automate the json file creation.

import base64
import os

directory = os.fsencode('.')

with open('ImagesData.json', 'wb') as jsonFile:
    jsonFile.write(bytes('{', 'utf-8'))

    written = False

    for file in os.listdir(directory):
        filename = os.fsdecode(file)

        if filename.endswith('.png'):
            with open(filename, "rb") as image_file:
                if written:
                    jsonFile.write(bytes(',\n','utf-8'))
                encoded_string = base64.b64encode(image_file.read())
                jsonFile.write(bytes(('"' +filename+ '":'), 'utf-8'))
                jsonFile.write(bytes('"data:image/png;base64,', 'utf-8') + encoded_string + bytes('"', 'utf-8'))
                written = True

    jsonFile.write(bytes('}', 'utf-8'))
  1. Copy the script to the image folder and run the script (requires python 3.6).
  2. A json file will the created with image name as key and base64 string as values.
  3. Copy the file to project and use (You can delete the images after that).
  4. Use the json file as mentioned above.


回答5:

I had the same problem but my situation was a little different. I had an array of different objects that needed dynamic images. I was already mapping the array, but I needed to match the images to that array based off of name. It was a little hacky, but this is how I went about it.

First, in my parent component I created a function to render a component for my array of objects. I passed the objects data into a prop called "object".

In my case I knew what my data was and I needed to match the corresponding image to the object that was being pulled off of an external api that I was grabbing my data from.

renderObjects() {
return this.state.objects.map(object => (
  <ObjectListDetail
    key={object.id}
    next
    props={this.props}
    object={object}
  />
));
}

In my ObjectListDetail component, I created a variable called icons, which was another array of objects. This time, I created a name property that would match the object being passed to the component from the parent and then had a second key called source in which I provided the path to the image. It went something like this.

var icons = [
{ name: "BTC", source: Images.btc },
{ name: "ETH", source: Images.eth },
{ name: "ETC", source: Images.etc },
{ name: "ZRX", source: Images.zrx },
{ name: "USDC", source: Images.usdc },
{ name: "LTC", source: Images.ltc },
{ name: "BCH", source: Images.bch },
{ name: "USD", source: Images.usd }
];

NOTE *** I had already required all of my images into a separate file for my entire app and imported them at the top.

I then created a variable called imgSrc and filtered the result to match the name of the object i was passing to the child component.

var imgSrc = icons.filter(
icon => icon.name === props.wallet.name
)

I then created an Image component and in the source requirement I called the result of the filter and pointed it to the source.

  <Image source={imgSrc[0].source} />

That is how I achieved dynamic image rendering within my application.

Its probably not the best way to do things, and I am still kinda new at this, but I would love any criticism