The task is simple: display a local image in a reactjs app based on dynamic data.
This is what I tried (assume path_to_image is derived dynamically):
<img src={require(path_to_image} />
generates an error:
Error: Cannot find module '../../images/logos/somelogo.jpg'
Without the require:
<img src={path_to_image} />
generates a broken image.
These two methods seem to be what people are doing, but no luck here. How do I solve this?
import image from "./path/to/image.png"
If you plan using more images in a dynamic way maybe you should store their paths in a db and then query the db for the respective path. Actually that's how it's done with a CMS for example. Even if you store the files on the same hosting, you would still save their paths to a DB instead of hardcoding.
Use this:
import SomeLogo from '../../images/logos/somelogo.jpg';
You can then use it like this:
<img src={SomeLogo} />
As for multiple images, you could store them in a JSON array, and then loop through them and add each image.
This does it:
let imageSrc = require("../../images/logos/generic.jpeg");
let dynamiclyGeneratedSrc = ...;
if (dynamiclyGeneratedSrc !== undefined) {
imageSrc = require(`../../images/logos/${dynamiclyGeneratedSrc}`);
}
Related
As the title says I have multiple images and I want to keep them in a json where it stores the url and from there I want to get image data accordingly.
Here is my codesandbox, I am not sure why it is not showing any images after going through a bunch of answers here.
https://codesandbox.io/s/confident-galois-2pn52
Seems like you forget one level
images
in JSON. Code of IMG in component should looks like this:
<img src={data.images.url} alt={data.images.name} />
You should use the JSON like
<img src={`${data.images.url}`} alt={data.images.name} />
Please update your code. It will start showing the images.
Your JSON structure has images object in it which you are not consuming.
I am currently using Next.JS to create a static website with the main objective to have a very good SEO-optimized website.
Everything works fine and the website is correctly deployed with Vercel, but I have noticed that part of the content is not present directly in the HTML files.
For instance, I have a component that loops over an array of data, using the array map method, like this:
{imageTexts.map((image) => (
<ImageText
key={image.title + 'TitleImage'}
title={image.title}
description={image.description}
size={imagesSize}
image={image.image}
/>
))}
Once the website is deployed to Vercel, I search inside the HTML file for the information/strings contained in the array of data (imageTexts), but I can't find them. I guess Next.JS uses javascript to target some sort of div and then loops over its own JSON file to dynamically display content.
For me, this seems to kill a lot of the SEO advantage that static websites have over SPA. Is there any way I can have those strings directly inside my HTML files?
I am still not 100% sure this is caused by the map method, but I don't find any other explanations. Especially because other dynamically loaded components don't have the same problem. For example, this component string can be found on the HTML file, without a problem:
{title ? (
<Text
type="h2"
textAlign="center"
>
{title}
</Text>
) : null}
If you are mapping over ImageTexts on the server and that component renders HTML tags, then that HTML should be sent on the first-page load, and you could see it if you do CTRL+U or disable javascript.
Ok, I have just found that the reason. It has nothing to do with the map method. I was actually using the <Remark> component from library called react-remark. It seems it does not play well with Next.JS
I have a component that represents a "badge". There are hundreds of types of different badges. Every badge is an individual SVG file. The badge component receives a slug for the badge it would need to use. The slug matches the file name. For instance: best-cheesecake would hint we need to display best-cheesecake.svg in the badge control.
Up till now, I've been loading svg images using:
import TestSVG from "../../images/test.svg";
and displaying them using:
<img height="50px" width="50px" alt="my-test-svg" src={TestSVG}/>
It's critical to understand I'm using WebPack and all images get their filenames hashed.
My question is about the best practice if my control needs to load one of the hundreds of SVG files. can my import dynamically using the filename string as it's given to the control via the props where those files get a hashed filename by webpack? Is there a better way? Obviously there has to be a way other than importing all SVG files in the folder...
use require.context concept you can import all the files located in a directory.
Below is the reference to what I have used earlier -
function importAll(r) {
let images = {};
r.keys().map((item, index) => { images[item.replace('./', '')] = r(item); });
return images;
}
const images = importAll(require.context('path/to/the/folder', false, /\.(png|jpe?g|svg)$/));
Now you can retrieve a particular image by its file name as below
<img src={**images[svg]**} className = {imgClassName} alt = {svg} />
where svg is filename with extension, ex. file1.svg
My solution was this:
I moved my 500+ badge SVG files from /src/images, where I keep all images into /src/images/badges
I have no explicit reference to any of the badge SVG files in my code so WebPack ignores them when creating the dist folder (both dev and production).
I installed WebPack's CopyPlugin and I use it to force the copy of /src/images/badges/*.svg into a badges under my default dist folder (it doesn't care they're not explicitly used in my code)
In my code, I can now use this successfully <img src={"/badges/" + this.props.badgeName + ".svg"}/>
In a render (returned from a function), I have:
{console.log(property.image)}
{console.log(typeof property.image)}
<Image src={require('./images/0.jpg')} fluid rounded />
Which renders the image correctly and console logs "./images/0.jpg" string
But when I try:
{console.log(property.image)}
{console.log(typeof property.image)}
<Image src={require(property.image)} fluid rounded />
I get:
Error: Cannot find module './images/0.jpg',
which doesn't make sense to me...
Also, I am unsure how to assign variables in render, I tried :
{ var abc = property.image }
but get:
./src/App.js Syntax error: Unexpected token (220:12)
If someone can help me understand why, I would greatly appreciate it.
I'm assuming you are using web pack or something similar (create react app or parcel, for instance). That's (usually) where the require function comes from, and why you can 'require' an image. But the only images you can require are local ones (images in your project source), not images on the web.
If you want to get an image from the web, require is not what you want. In that case, you just pass the url as a string to the src property.
However, if you do need images that are in your project source, then you would probably use require. Most of the time, you use require at the top of a file, and pass it a string, not a variable. This is because your packager reads the file before packing it up, and looks for any requires, so that it can include them in the package. But when you pass require a variable, it can't do that. However, you can use require.context if you want to load files dynamically from a directory.
So you probably want this at the top of your file:
const pathToImages require.context('./images', true);
and in your render:
<Image src={pathToImages('0.jpg')} fluid rounded />
or
<Image src={pathToImages(property.image)} fluid rounded />
I'm basically trying to have a dynamic ending on a link, with the link ending coming from state array that was created with fetching information from a database.
I'm using map to go through all the items on the array and I'm trying to render thumbnails of all the images in the array. However, I'm not quite sure how the syntax works in JSX.
I've already tried injecting javascript and tried bracketing it from various places but haven't found a solution.
{picArr.thumbnails.w160}
Contains the tokens for the thumbnails to be reached.
<img src='http://media.rr.randomexample.com/wbma/media/' {picArr.thumbnails.w160} alt={picArr.title} />
Have you tried this?
<img
src={'http://media.rr.randomexample.com/wbma/media/' + picArr.thumbnails.w160}
alt={picArr.title}
/>