1

I have a Typescript program with a readable name : img_path mapping saved in a .ts file. Based on certain criteria, I want to pass in an individual entry to a component which will then display the readable name as a title and under it show the image saved in img_path. I can do this in Javascript fine, but for some reason in Typescript, it won't let me use require. The solution I'm used to would be something like:

<img src={require(props.imgPath)} />

However, in Typescript that gives me the error: Uncaught ReferenceError: require is not defined

From what I've researched, I should be using import, something like:

import myi from "src/assets/myImage.png"

and then in my render function, do

<img src={myi} />

However, since imports have to be done at the top of the file, you can't use variables passed into the component. So that won't work for a dynamically decided pairing. (One option would be to import every individual image, but there are a lot of images, and if I change the mapping at all, I would have to find all component files and update them there too).

How can I pass a string with the image path to a Typescript component and have that component display the image, without using import or require?

4
  • Does this answer your question? How do I reference a local image in React? 15th time the same question this week Commented Aug 15, 2022 at 13:57
  • @KonradLinkowski Unfortunately, it does not. The only suggestions it seems to give are the ones that do not work (e.g. require does not work with Typescript and import is unwieldy for thousands of images). That's why my question asks if there's a solution that's not either of those. Commented Aug 15, 2022 at 14:14
  • Did you read other answers? stackoverflow.com/a/57291453/5089567 Commented Aug 15, 2022 at 14:18
  • Yes, but just {path} passed to src doesn't work, and the comments etc below those answers all affirm that those "answers" actually need require to wrap the string. Commented Aug 15, 2022 at 17:50

2 Answers 2

1

The most consolidated way I've found to do this is to create a separate images.ts file whose content is of the form:

import img0 from "filepath0"
import img1 from "filepath1"
...
import imgN from "filepathN"

export const images : {[key:string] : any} = {
    "filepath0" : img0,
    "filepath1" : img1,
    ...
    "filepathN" : imgN,
}

Then in any file where you want to use the images, you call:

import { images } from "../images";

Then you can just pass the path into the images object (e.g. images[props.imgPath]) to get the actual image. For example:

// RENDER
return <img src={images[props.imgPath]} />;

(Note: Alternatively, you can reference an image using just the image name rather than its full path by storing the name as the key in the images object rather than the path itself)

--- Extra ---

If you have a lot of images, you don't want to have to write out the images.ts file by hand. I used the following to make it easier to create.

Part 1: Get image file names

In the folder containing your images (and hopefully just your images), open a command terminal and run:

dir /b /a:-d /o:n > filelist.txt

(The dir gives a list of files, the /b /a:-d /o:n gives just the name not any other details such as size or date, and > filelist.txt saves the output to a txt file rather than the terminal itself.)

Open the file and remove "filelist.txt" from it any any other name that isn't an image.

Part 2: Get list of imports

In the folder where "filelist.txt" is saved, run the following using Python (either using python in a command terminal or a python IDE):

with open("filelist.txt") as f:
    names = [x.strip() for x in f.readlines()]

This creates a list names of all the image file names (with the \n at the end of each line in the original text file removed).

Create a new list that's the full paths for the image as react would want to see it:

paths = [PATH + name for name in names]

What you put in PATH will be the same for each image. E.g.

paths = ["src/MyApp/assets/" + name for name in names]

Then do:

for i in range(len(names)):
    print ("import img" + str(i) + " from \"" + paths [i] + "\"")

This will print out all the import img0 from "filepath0" lines you need for your react images file. Copy them into your react file.

Part 3: Get mapping object

Type export const images : {[key:string] : any} = in your react file.

Then run the following in your python program and paste the output in your react file after the equal sign:

dict([(paths[i], "img" + str(i)) for i in range(len(paths))])

This outputs the dictionary (Javascript object) comprised of "filepath0" : img0" statements.

If you want each "filepath0" : img0" to be on its own line instead of one after another, use python print statements instead:

print ("{")
for i in range(len(paths)):
    print("    \"" + paths[i] + "\" : img" + str(i) + ",")
print ("}")

Copy the output into your react file, being sure to delete the , after the very last "filepath0" : img0" line.

Sign up to request clarification or add additional context in comments.

Comments

0

/images/index.tsx file

// step 1: import the image 
import logoDark from './images/logo-dark.png'
import logoLight from './images/logo-light.png'
import appIcon from './images/favicon.png'

const assets: any = {
// not working 
// images: {
//   logoDark: require('./images/logo-dark.png'),
//   appIcon: require('./images/favicon.png')
// },

// working 
// step 2: import the image 
  images: {
    logoDark: logoDark,
    logoLight: logoLight,
    appIcon: appIcon
  },

}

export default assets

usage/render

//client/src/layout/appLayout.tsx file
import assets from '../assets'
<img
src={assets.images.logoLight}
style={{ width: '100px' }}
alt='app logo'
/>

1 Comment

Please include a brief explanation of how and why this solves the problem. This will help future readers to better understand your solution. - From Review

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.