I have a component image which is using a value, coming from a loop.
something like:
arr.map(m => <Component imgsrc={m.src} />)
where src prop is a link to the image folder.
then I do
<img src={require(`${props.imgsrc}`)} />
but if does not work, however if I use it statically
<img src={require(`same-path-as-src`)} />
it works.
What is the difference?
Webpack needs to know in what directory to look, since it needs to know at build time what directories to include in the build. If the entire path is dynamic, Webpack would need to include the entire file system in the build, which would not be feasible.
You can make parts of the path dynamic if Webpack can figure out where to look.
<img src={require(`../images/${props.imgsrc}.png`)} />
Related
We have hundreds of SVG files that I am trying to render inline. I am using create-react-app which already has #svgr/webpack installed and configured. It allows me to add SVG inline like so:
import { ReactComponent as SvgImage } from '../Plans/Brownlow-Floor-Plan.svg';
...
<SvgImage style={{ width: "600px !important" }} />
Similar question provides a solution for dynamically rendering SVG inline. However, In my case, I don't have any SVG files in the source code. Instead, all SVG files are returned to me via a call to an API service. For example:
http://myservice/api/getplan(100)
http://myservice/api/getplan(103)
http://myservice/api/getplan(106)
http://myservice/api/getplan(631)
As a result, by the time webpack is run, it has no information about these SVG files.
So my question is: is it possible to render svg dynamically in react (TypeScript) if I pull SVG file from an external URL?
This is not a duplicate question:
How to dynamically import SVG and render it inline
Approach described in the question above is not going to work because it expects all SVG files to be added to the source code.
This approach also not going to work because simply using an img tag will not pull SVG inline:
<img src="plan.svg" />
Including SVG via an img tag make these kinds of things impossible:
Any help will be greatly appreciated!
There's an excellent package called react-svg that does exactly what you want.
You can use it with a simple src property that takes a url string, just like an <img> tag. But behind the scenes, it will download the svg file from the url and inject it inline. For example:
import { ReactSVG } from 'react-svg'
Component = () => <ReactSVG src="http://somewhere.com/my.svg" />,
I am not sure if this will work for you but, you can try to using the tag <use /> within an <svg /> tag. For example:
<svg
height={iconHeight}
viewBox={`0 0 ${iconWidth} ${iconHeight}`}
width={iconWidth}
>
<use xlinkHref={`${svgPath}#${icon}`} />
</svg>
Where svgPath is the URL to the SVG, and icon is an ID set on the SVG. You can try to omit to the #${icon} portion.
Not sure if this helps though.
If you choose this route, you may be incompatible with IE... For that you can use svg4everybody, but tbh IE is dead and it should stay dead.
Cheers!
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.
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
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
I'm attempting to display an image in a React component as part of a project using webpack and webpack-dev-server.
So far I have completed the following steps:
Used npm to install file-loader
Updated webpack.config.js to add a loader for image files
Imported the image I want into my component
Used the import in my img tag
Having taken these steps, webpack fails to compile with a 'cannot find module' error:
ERROR in [at-loader] ./src/components/App.tsx:4:26
TS2307: Cannot find module '../images/kitten-header.jpg'.
My folder structure is as follows:
/dist
/images
kitten-header.jpg
bundle.js
bundle.js.map
/node_modules
(content ignored for brevity)
/src
/components
App.tsx
/images
kitten-header.jpg
/styles
App.less
index.tsx
index.html
package.json
tsconfig.json
webpack.config.js
The new loader that I added to my webpack.config.js is:
test: /\.(jpe?g|gif|png|svg)$/, loader: "file-loader?name=./images/[name].[ext]"
I've imported the image file, in App.tsx, like this:
import kittenHeader from '../images/kitten-header.jpg';
...and used the import in an img tag like this:
<img src={ kittenHeader } />
Note: Full text of webpack.config.js and App.tsx were provided until I got a little bit closer to the answer and realized they weren't relevant (see update 1).
I assume I'm making some very trivial error with regards to the relative path in the import. As you can imagine, I've tried various alternatives.
Can anyone provide some insight?
For reference, as I'm continuously hitting articles and questions relating to the wrong version of webpack, here are my versions:
React 15.5.4
Webpack 2.6.1
Webpack-dev-server 2.4.5
TypeScript 2.3.2
Update 1: 2017.06.05
So, looking at this SO question and this post on Medium, I've been able to identify that the problem lies not with how I've used webpack, but with that fact that I'm using TypeScript. The error is a typescript error caused by the fact that the typescript compiler doesn't know what a .jpg file is.
Apparently, I'm going to need to provide a d.ts file or use a require statement.
Almost there...
With regular require, this is how I use it in a tsx file:
const logo = require('../assets/logo.png');
...
<img alt='logo' style={{ width: 100 }} src={String(logo)} />
Hope this helps. importing did not work for me, either.
This is how I get it working:
// This declaration can be move in some common .d.ts file, will prevent tslint from throwing error
declare function require(path: string);
const SampleComponent = () => (
<div>
<img src={require('./styles/images/deadline.png')} alt="Test" />
</div>
);
The way you proposed in your answer will end up writing modules declaration for each image file being placed in components.
The error, TS2307: Cannot find module '../images/kitten-header.jpg', is highlighting that the TypeScript compiler does not understand the import of a .jpg file.
The webpack configuration is fine, as evidenced by the image file being copied to the dist folder successfully despite the compile error.
There are two ways that we can resolve the issue.
Firstly, we could bypass the TypeScript import by using a 'require' statement. To do this, the import...
import kittenHeader from '../images/kitten-header.jpg';
...can be replaced with a require...
const kittenHeader = require('../images/kitten-header.jpg');
...and that should be all that's needed.
Note that, in my case I also needed to install some typings to support the 'require' statement. Without these, I was getting a TS2304: Cannot find name 'require' error.
Originally I used #types/node, as described in this SO answer, but #EvanSebastian pointed out that node is intended to support writing NodeJS modules, which is not what I'm doing (see comments on the question).
I tried #types/webpack-env, as suggested, but this resulted in a TS2322: Type '{ src: {}; }' is not assignable to type 'HTMLProps<HTMLImageElement>'. error against the src property of my image tag.
Most recently, I've switched to using #types/requirejs, which I'm hoping is focused enough to avoid including a load of inappropriate additional types. It is currently working:
npm install #types/requirejs --save-dev
Alternatively, we could keep the import and provide a d.ts file with type information declaring an appropriate module. I've not been able to discover exactly what this file would look like.
Add a typescript definition file anywhere in your src directory and (name it something like image.d.ts)
Export a module definition for jpeg files like so:
export module "*.jpg";
Try my code, in any React-Typescript component you want
import * as logo from './assests/icon.jpg';
const img = logo.default;
const Comp = ()=> {
return <img src={img} alt="image" className="" />
}
const logo = require('../../../assets/img/logo.svg')
<img src={logo.default} style={{ width: "100%", height: "50px" }} alt="" />
In addition to mcku's answer you can also use imports this way:
// #ts-ignore
import * as kittenHeader from '../images/kitten-header.jpg';
...
<img alt='logo' style={{ width: 100 }} src={logo} />
Although you have to ignore the warning.