Dynamically Importing Images Based on a Variable - reactjs

I have a requirement to select, from a local source, an image based on the value passed back from the REST API I am using. For example:
//Psuedo-call from the API
var imageIdToSelect = response.data.imageId
//Then later in the render()
<img src={ baseUrl + imageIdToSelect } />
I have a solution to this, which is to use require() as that allows me to append the url as such:
<img src={ require(baseUrl + imageIdToSelect) } />
This works fine, however, I am using a Microsoft TSLINT setup that does not allow require() over the prefered import at the top of the file "no-require-imports".
I know I am not meant to let linting tools control my work to the point where I am just blindly following rules. So my question is two-fold:
Why is it frowned upon to use require() in such a way. One reason I could think of is that if all of the external files/resources are declared at the top of the file, then you don't have to look through the source to find them hidden in functions.
What would the import x from './' solution look like here? I have seen people creating index.js and index.d.ts files inside their image folders to import and export all the images inside but that seems a tad extraneous.
Edit: I also have just realised that using require() with a non-literal string is a violation of my ts-linting too.
Thanks in advance

Related

React unable to display images from local path

I'm new to react, I'm trying to display images from the src/images folder.
but after inserting the correct path, then also the image is not visible.
Here you can see my img tag path and on the left side folder structure
From the Image you provided, looks like you used require("path...") which is not a good way to do so, its valid tho, but not a good practice, its recommended and is common to use import X from "somewhere" syntax.
I suggest you to use either of these two ways to use images in react.
put images in public folder and use relative links in the href tag, i.e:
<img href="/images/panda.png" alt="cute panda" />
put images inside a folder somewhere inside src folder like you did in the image and import images using ES import syntax, and use imported image variable in {} expression for src prop, i.e:
import PandaImg from "../images/panda.png"
const Panda = ()=>{
return <img src={PandaImg} alt="cute panda" />
}
Here is a CodeSandbox Example may help you further explore the code in broader context.

Import a file as a string (or source asset) in Gatsby / React

I want to import .ts, .tsx, .js, and .jsx files into a react component and render them within a PrismJS highlighting block. For example, let's say I have a TypeScript file with functionA in it that I want to highlight in my actual website:
functionA.ts:
export function functionA() {
console.log("I am function A!");
}
I want to include this in a different component. The problem is, when I import it, I am obviously importing the webpack module version of it. My weak attempt at trying to get my function render in a react component looks like this:
MyComponent.tsx:
import * as React from "react"
import { functionA } from "./functionA"
export function MyComponent() {
return (
<>
<h1>Here is your code block:</h1>
<pre>
<code>
{functionA.toString()}
</code>
</pre>
</>
)
}
and what will actually render on the page where the code block is will look something like this:
Here is your code block:
WEBPACK__IMPORT.functionA() {
console.log("I am function A!")
}
I can't exactly remember what the .toString() function output looked like, but the point is it is NOT just the contents of the file how it appears in a code edit for example - it has been modulized by WebPack.
So, in a Gatsby project, how can i get these various code snippets to be imported directly as a string, purely as they are written, without WebPack enacting its import stuff on it? Is there a plugin or some way to tell Webpack to use the imported file as its asset/source module type? I know for MD or MDX files there is the gatsby-remark-embed-snippet, but I am building a component based HTML page and can't use MD or MDX files!
It's very late, and perhaps I just can't see the forest from the trees, I know there must be a way to do this...
You need to require the file using webpack's raw-loader, i.e:
const functionA = require("!!raw-loader!./functionA");
This works for create-react-app, as in the solution discussed here, and this works for Gatsby as well!
After using require on such a file, the file contents can be rendered in the component as:
<pre>{functionA.default.toString()}</pre>
It's then up to you to add syntax highlighting using a tool like prism or similar.
Note this solution will only work as long as Gatsby V3 continues to use WebPack v4, as raw-loader is deprecated in WebPack v5 and will be phased out for asset/source type modules.

Can't Render Image When Path Stored in React Variable

I have a lot of images I need to use in my react app, so I don't want to import them one by one. To that end, I'm using reqiure(). However, while require works when used like this below:
return <img src={require("./images/lets_go.png")} />
if I store that path in a variable:
let v = "./images/lets_go.png";
return <img src={require(v)} />
I get Error: Cannot find module './images/lets_go.png'
Why won't it allow me to use the path stored in a variable (it's the exact same path) and how can I make it work?
this will work using a 'Partial' require, where you give the path as text and and the image name can be the varible. the reason this is happening is related to how webpack is meant to handle static paths.
What we know works, (static image path):
<img src={require("./images/lets_go.png")} />
Trying to make the path a varible like this we found does not work
let v = "./images/lets_go.png";
<img src={require(v)} />
What will work when trying to make the path a varible
let v = "lets_go.png";
<img src={require(`./images/${v}`).default} />
Note that .default needs to be added at the end of the require as of may/2021 due to a error related to react scripts. this might be fixed and not needed if you're reading this in the future.
you'll need to store all your images in the same folder of course, but this lets you dynamically load high volumes ofimages in react/js without needing to manually import them all into the code.
Either you may import the image and bind it to src attribute like its done in create-react-app with the logo as follows:
import logo from './logo.png' // relative path to image
class Home extends Component {
render() {
return (
<img src={logo} alt={"logo"}/>
)
}
}
Or, if you used create-react-app cli to create your project then your public folder is accessible. Just create the images or assets folder in public and you may access it in jsx as follows:
public/images/ -> store images here
<img src="/images/home.png" /> -> use it like this in jsx

What the best way to import assets in React JS?

I'm currently working on a project with React JS, that contains lots of assets. And actually, I'm wondering what is the best way to import assets between these two methods :
- Creating a JSON file that contains all informations, with their assets paths (eg. mySuperImg: "../assets/img/myImage.jpg" then using the path for my image tags)
- Importing all assets directly in the component (or using the Context API, perhaps?) (eg. import {myImage} from "../assets/myImage.jpg" then using the img tag with that path <img src={myImage} alt="My Image"/>)
My questions : What the best way to import assets ? Is there a speed difference between these two methods ?
Thanks! Take care!
I'd say it depends on you. Whichever way you feel comfortable, you should go for it. Generally, I import the assets in the corresponding file, but the other way can also be used. Instead of json, you could use js approach as well, similar to how we export actions, for eg,
export const ADD_PROJECT = "add_project";
export const FETCH_PROJECTS = "fetch_projects";
You could use something like,
export const IMAGE = require("the location to your image");
To answer if it would take more time, I don't think that there would be any performance issue, as we use a similar approach for the actions most of the times.
it's best to keep the images in assets and use them in your source, if you work with the JSON file then you have to keep track of both of them and it will mess up as you say you have a lot of assets.

Avoiding a long list of imports in React

For a SET game that I am creating in React (using Create React App), I need to import 81 image files representing the 81 possible cards used in the game. With the help of a Python script, I created this extremely long list of imports
import i0000 from './assets/0000.png'
import i0001 from './assets/0001.png'
[...]
import i2221 from './assets/2221.png'
import i2222 from './assets/2222.png'
and since I will need to reference those variables using strings representing each card, I have this object:
const refs = {
'0000': i0000,
'0001': i0001,
[...]
'2220': i2220,
'2221': i2221,
'2222': i2222
};
The good thing is that now I have all the card images pre-loaded to be called easily with
<img src={refs[card]} />
But the bad thing is I have 164 lines of ridiculous code that make it work. I'm wondering if there is a better way to pre-cache and reference a directory full of images.
Move all the images to your public folder, say public/cards.
Then you can reference them with <img src={`cards/${card}.png`} /> without the need for any import statement.
Webpack can no longer warn you if the referenced images are missing though, so just make sure they are there.
Two approaches:
First, you eliminate manually creating the refs object by struturing your code like this:
export i0000 from './assets/0000.png'
export i0001 from './assets/0001.png'
And where you want to use these assets:
imports * as refs from './assets'
<img src={refs[card]} />
Secondly, you could use a bundling system that supports dynamic requires e.g. https://webpack.github.io/docs/context.html#dynamic-requires

Resources