Rohit Girdhar
Rohit Girdhar

Reputation: 353

React Native Dynamic Images

I'm reading a JSON file which has the names and the image URI of certain people. While iterating over the structure I'm able to print the names but can't get the Images to show up. I've also read that React doesn't support dynamic images so I did a workaround as suggested here.

JSON

[
  {
    "id": 1,
    "name": "Rohit",
    "uri": "assets:/rohit.jpg",
    "special": "text1"
  },
  {
    "id": 2,
    "name": "Anmol",
    "uri": "assets:/rohit.jpg",
    "special": "text2"
  },
  {
    "id": 3,
    "name": "Bhavya",
    "uri": "assets:/rohit.jpg",
    "special": "text3"
  }
];

Main Component

import React, {Component} from 'react';
import { StyleSheet, Text, View, Image, ScrollView, Button, TouchableWithoutFeedback, TextInput, AsyncStorage} from 'react-native';
import { createStackNavigator } from 'react-navigation';
import customData1 from './customData.json';

class HomeScreen extends React.Component {
  render() {
    const initialArr = customData1;
    return (
      <View style={styles.container}>
        <ScrollView vertical={true} contentContainerStyle={{flexGrow: 1}}>
          <Text style={styles.category}>Category 1</Text>
          <ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>
            <TouchableWithoutFeedback onPress={() => {
              this.props.navigation.navigate('Details', {});
            }}>
              <View style={styles.view}>
                {initialArr.map((prop, key) => {
                  return (
                    <View style={styles.container}>
                      <Image source={{uri: {prop.uri}}} style={styles.image}></Image>
                      <Text key={key}>{prop.uri}</Text>
                    </View>
                  );
                })}
              </View>
            </TouchableWithoutFeedback>
          </ScrollView>
        </ScrollView>
      </View>
    )
  }
}

Upvotes: 3

Views: 13002

Answers (1)

Chad Nehemiah
Chad Nehemiah

Reputation: 881

Depending on the number of images that you are expecting you could try placing an images.js file in your assets/images folder and require them as such:

// assets/images/images.js
const images = {
 rohit: require("./rohit.png"),
 bhavya: require("./bhayva.png")
}
export default images;

Then in your MainComponent, if you were to trim off the assets:/ part of the string in the uri then you could use:

import images from "../assets/images"

{initialArr.map((prop, key) => {
  return (
    <View style={styles.container}>
      <Image source={images[prop.uri]} style={styles.image}></Image>
      <Text key={key}>{prop.uri}</Text>
    </View>
  );
})}

If you are dealing with a large number of images, then your images.js file will become difficult to maintain, in that case you could try using a plugin like https://github.com/dushaobindoudou/babel-plugin-require-all and then write a small script which will create an dictionary of your images like:

// prepareImages.js
const fs = require("fs");
const files = fs.readdirSync("./assets/images").filter(x => x.includes("png"));
const ex = "{\n" +
files.map(x => `"${x.split(".png")[0]}": require("./${x}"),`).join("\n") + "}";
const res = "export default " + ex;
fs.writeFileSync("./assets/images/index.js", res);

Upvotes: 12

Related Questions