How to load local dynamic images with html in React Native
Tags: reactnative, mobile, html, image
Published: 2021-07-02 22:47:07


First we will need to use [react-native-render-html](https://github.com/archriss/react-native-render-html)

(I like it because it doesn’t use WebView, and WebView for this kinda thing is bad.)



But there is a problem, this lib doesn’t have a way to load **local** images out of the box. For that** you need to create a custom image tag and add it to your HTML component**

Like this:
```js
const htmlContent = ` 
  <h1>This HTML snippet is now rendered with native components !</h1>
  <img source="./src/assets/michael.jpg"/>
  <h2>Enjoy a webview-free and blazing fast application</h2>
  <em>Some random sentence!</em>
`;


        <HTML
          renderers={{
            img: (attribs) => {
              const imagePath = attribs.source;
              console.log(imagePath);
              return (
                <Image
                  key={attribs.source}
                  style={styles.imageContainer}
                  source={require('./src/assets/michael.jpg')}
                />
              );
            },
          }}
          source={{html: htmlContent}}
          contentWidth={contentWidth}
        />
```

Here i’m creating a custom tag named **img** inside **renderers** prop and defining it as an <Image> component with an image path that i have selected.

And that’s the result:

![](https://cdn-images-1.medium.com/max/2000/1*H-8v5k9JCDJvwz1gYXohjw.png)

But the main problem isn’t solved, our goal is to render **local images dynamically** using that custom tag that we’ve created.

After this maybe you’re thinking:

-“Just pass the image path as a prop to the `<img/>` tag and voila, you’re done!”

OK, that sounds right, but how do I pass the image path that I want our custom tag to render?

I added a source prop with the image path in `<img>` tag.

    <img source="./src/assets/michael.jpg"/>

And i am getting it inside our img function adding **attribs **as a parameter

Now i can access the image path using **attribs.source**

```js
const htmlContent = ` 
  <h1>This HTML snippet is now rendered with native components !</h1>
  <img source="./src/assets/michael.jpg"/>
  <h2>Enjoy a webview-free and blazing fast application</h2>
  <em>Some random sentence!</em>
`;


        <HTML
          renderers={{
            img: (attribs) => {
              const imagePath = attribs.source;
              console.log(imagePath);
              return (
                <Image
                  key={attribs.source}
                  style={styles.imageContainer}
                  source={require('./src/assets/michael.jpg')}
                />
              );
            },
          }}
          source={{html: htmlContent}}
          contentWidth={contentWidth}
        />
```


This will output in the console:

    "./src/assets/michael.jpg"

Now, if we try to change line 18 like this:

    require('./src/assets/michael.jpg);

    to

    require(imagePath);

We are going to get this error:

    [Error: TransformError App.js: App.js:Invalid call at line 31: require(imagePath)]

**That’s because all the imports have to be a string, not a dynamic expression.**

Maybe now you’re thinking:

“-If he is writing a post on Medium its because there’s is a way to import dynamic imports inside require, right?”

Well, no…

Let me show you what we are going to do:

One thing we know for sure, you can normally import images like this:

```js
 const imagesList = {
    dwight: require('./src/assets/dwight.jpg'),
    michael: require('./src/assets/michael.jpg)
  }

const htmlContent = ` 
  <h1>This HTML snippet is now rendered with native components !</h1>
  <img source="./src/assets/michael.jpg"/>
  <h2>Enjoy a webview-free and blazing fast application</h2>
  <em>Some random sentence!</em>
`;


        <HTML
          renderers={{
            img: (attribs) => {
              const imagePath = attribs.source;
              return (
                <Image
                  key={attribs.source}
                  style={styles.imageContainer}
                  source={imagesList[imagePath]}
                />
              );
            },
          }}
          source={{html: htmlContent}}
          contentWidth={contentWidth}
        />
```

So, i’m creating an object with all my images and it’s requires as properties of that object.

    const imagesList = {
        dwight: require('./src/assets/dwight.jpg'),
        michael: require('./src/assets/michael.jpg)
      }

Now i can finally pass the image that we want to render in the source property in our custom <img/> tag.

    <img source="michael"/>

We also need to modify the Image component to something like this:

    <Image
       key={attribs.source}
       style={styles.imageContainer}
       source={imagesList[imagePath]}
     />

Now, if i change

    <img source="michael"/>

    to

    <img source ="dwight"/> 

Th will be the result:

![](https://cdn-images-1.medium.com/max/2000/1*u_9MDByFRba5GEETehSj8Q.png)

## Conclusion

The best way to implement this solution is to isolate your **imageList** variable in another file, and add each one of your images and it’s paths manually or you can create a script that does all the hard job for you (like i did).

You can learn how to create this script on [this](https://dev.to/emilios1995/dynamic-imports-in-react-native-9k5) tutorial.

You can find the project source code [here](https://github.com/juniorklawa/html_local_image)

I hope this has helped you ;)