JSX - dynamically rendering local images - reactjs

I'm trying to map through an array of objects, rendering local images, but have painfully found out that this can't be done the same way as rendering external urls, with the images not firing.
Not been able to find a solution without cheating and declaring local images declaratively - import Logo from ... - or placing the images in the public folder, which could give me cache issues down the line. I've tried image: require("") in the array but it doesn't seem to respond.
Surely this can be done dynamically? If anyone knows of a solution to the below it would really help me out.
Directory.jsx
this.state = {
categories: [
{
title: "Burgers",
image: "../../images/Burger_landing.jpeg",
id: 1
},
{
title: "Sides",
image: "../../images/Fries_main.jpeg",
id: 2
},
{
title: "Shakes",
image: "../../images/Shakes_main.jpeg",
id: 3
}
]
};
}
render() {
return (
<div className='menu__container-position'>
{this.state.categories.map(({ title, image, id }) => (
<DirectoryItem key={id} title={title} image={image} />
))}
</div>
);
}
DirectoryItem.jsx
const DirectoryItem = ({ title, image }) => {
return (
<div
className='menu__container-img'
style={{ backgroundImage: `${image}` }}
>
<h1>{title}</h1>
</div>
);
};

You should set the image URL like below
backgroundImage: `url(${image})`
Or
backgroundImage: "url("+image+")"
If images are not in a public path
backgroundImage: `url(${require(image)})`

Related

How to get the URL/source of an image that has been attached and uploaded to MongoDB?(wysiwyg)

I am creating a blog-post website via markdown(with NEXTJS and Typescript) and the issue that I am currently facing is in the panel where the post is being created when image from /url or source from local machine/ is being submitted.
The panel does preview the image in the textarea element but once submitted to my MongoDB collection, what I get is an empty space in the place of the image. The packages that I am using are - react-draft-wysiwyg - which is the package that enables me to create content and providing me with the creation panel in markdown version and also the package that helps attach images - and for rendering I am using react-markdown - so I can be able to convert markdown to html - used along with remark-gfm as a plugin for the render.
So the question is how can I can also attach/get the url/source of the given image in markdown to my database collection while using react-draft-wysiwyg as apparently they doesn't respond much in their Github(https://github.com/jpuri/react-draft-wysiwyg/issues/1307)
Here is the my code for the creation panel of the blogpost
<Editor
wrapperClassName="demo-wrapper"
editorClassName="demo-editor"
contentState={contentState}
onEditorStateChange={(editorState) => {
setEditorState(editorState);
}}
toolbar={{
image: {
previewImage: true,
urlEnabled: true,
uploadEnabled: true,
uploadCallback: () => {
return new Promise((resolve, reject) => {
resolve({
data: { link: convertedData.entityMap[0].data.src },
});
});
},
},
}}
/>
<textarea
disabled
hidden
onChange={(e) => console.log(contentTextArea)}
value={
editorState &&
draftToMarkdown(
convertToRaw(editorState.getCurrentContent()),
{
entityItems: {
image: {
open: function (entity) {
console.log(entity);
return 'open';
},
close: function (entity) {
// #ts-ignore
console.log(entity);
return 'close';
},
},
},
}
)
}
/>
</div>
</div>
And that's how I am trying to render it
{result.map(
(post: any, index: React.Key | null | undefined) => {
return (
<>
<h4 key={index} className="text-2xl text-center pt-20">
{post.title}
</h4>
<ReactMarkdown
remarkPlugins={[gfm]}
className="text-left px-4"
>
{post.body}
</ReactMarkdown>
</>
);
}
)}
This is also what is submitted to my collection in Mongo while trooubleshooting
Hopefully I have managed to explain properly the trouble I'm facing,thank You in advance for the shared time and wisdom!

Render a React component by mapping an array inside of an array of objects

I have trouble rendering a react component by mapping an array nested inside an array of objects.
I have this React component, which is simple images
function ProjectLangIcon(props) {
return (
<img className="project-icon" src={props.src} alt={props.alt}/>
)
}
This component is a part of this bigger one :
function Project(props) {
const projectLang = projectList.map(projects => {
return projects.lang.map(langs => {
return <ProjectLangIcon
key={langs.key}
src={langs.src}
alt={langs.alt}
/>
})
})
return (
<div className="project">
{props.title}
<div className="project-content">
{projectLang}
</div>
</div>
)
}
I'm mapping the data from this file :
const projectList = [
{
key: 1,
name: "Site de mariage from scratch",
link: "https://mariage-hugo-et-noemie.fr/view/index.php",
lang: [css, html, javascript, php, mySql]
},
{
key: 2,
name: "Site de paris sportifs",
link: "https://akkezxla.ae.lu/Akkezxla-Betting-Site/bet-list.php",
lang: [css, html, javascript, php, mySql]
},
{
key: 3,
name: "Site de location d'appartement",
link: "http://paris-island.com/",
lang: [wordpress, css, javascript]
}
]
with the lang array being constitued of objects like these :
const css = {
name: "CSS",
src: cssIcon,
alt: "Icône CSS"
}
const html = {
name: "HTML",
src: htmlIcon,
alt: "Icône HTML"
}
Then, I map the projects component inside the Realisation component like this :
function Realisation() {
const projects = projectList.map(item => {
return <Project
key={item.key}
title={item.name}
link={item.link}
/>
})
return (
<div className="realisations pro-block">
<BlockTitle
title="Réalisations"
close={closeReal}
/>
<div className="realisation-content">
{projects}
</div>
<BlockNav
left="Compétences"
switchl={switchComp}
center="Parcours Porfessionnel"
switchc={switchParcoursPro}
right="Parcours Académique"
switchr={switchParcoursAcad}
/>
</div>
)
}
the result I get is this : enter image description here
But I want each projects to have its corresponding language icons.
Does anyone have an idea of hiw I should proceed ?
Your issue is due to Project component. You are rendering this component for each Project of projectList but inside of this component you are not taking in the account the actual Project that is passed to this component.
Project (component)
const projectLang = projectList.map(projects => {
return projects.lang.map(langs => {
return <ProjectLangIcon
key={langs.key}
src={langs.src}
alt={langs.alt}
/>
})
})
Lines above are building the same projectLang for any Project you passed to this component. And is building it from All the projects you have, it returns the array of arrays. So [[all_icons_of_project_1], [all_icons_of_project_2], ...].
Here is what you should do:
First: You need to modify Product component to either pass a product item itself, either to pass additional property, langs in your case. And to modify .map function a little.
Notice: i destructured the props object passed as a parameter to Product component. Also, i wrapped the map function into useMemo for optimization purposes.
function Project({ title, link, langs }) {
const projectLang = useMemo(() => {
return langs.map((lang) => (
<ProjectLangIcon key={lang.key} src={lang.src} alt={lang.alt} />
));
}, [langs]);
return (
<div className="project">
<a href={link} className="project-txt" target="_blank">
{title}
</a>
<div className="project-content">{projectLang}</div>
</div>
);
}
Second - just pass the langs attribute (prop) to your Product component. (Again, i wrapped it into useMemo, for optimizations)
function Realisation() {
const projects = useMemo(() => {
return projectList.map((item) => (
<Project
key={item.key}
title={item.name}
link={item.link}
langs={item.lang}
/>
));
}, []);
return (
<div className="realisations pro-block">
{/* ... */}
<div className="realisation-content">{projects}</div>
{/* ... */}
</div>
);
}
Note - no icons in codesandbox, only placeholders and alt text.

How do I render png images in reactJS using map [duplicate]

So in a Reactjs class component, I have an array in my state like this:
myArray: [
{ number: 1, title: 'Users', image: '../../../assets/images/website/homepage/users.png' },
{ number: 2, title: 'Clients', image: '../../../assets/images/website/homepage/clients.png' },
{ number: 3, title: 'Admin', image: '../../../assets/images/website/homepage/admins.png' },
]
and I mapped the array this way:
{this.state.myArray.map((item, index) => (
<Box key={index} className="col-sm-12">
<img src={ item.image } className="img-fluid" alt={item.title} />
<Typography variant="h4">{item.number}</Typography>
</Box>
))}
Now, everything works fine, except the image that doesn't display, I really don't understand where I'm getting it wrong.
Note that, if I copy one of the image links directly inside the src using require method, it works. Kindly help.
You can require dynamically with proper expression:
Change image to (remove ../../../assets/images/website/homepage/ and .png):
const myArray = [
{
number: 1,
title: 'Users',
image: 'users',
},
{
number: 2,
title: 'Clients',
image: 'clients',
},
{
number: 3,
title: 'Admin',
image: 'admins',
},
]
And to render at UI (add directory path and the extension inside require):
{myArray.map((item, index) => (
<Box key={index} className="col-sm-12">
<img
src={require('../../../assets/images/website/homepage/' +
item.image +
'.png')}
className="img-fluid"
alt={item.title}
/>
<Typography variant="h4">{item.number}</Typography>
</Box>
))}
Why it works?:
Webpack can understand this expression, by generating context about directory and extension, and can load all the matching modules.
I think you are missing require.
Like:
<img src={require(item.image)} />

How to map one image at a time with Alice carousel?

I am trying to add a carousel for my products.
I have an array of url images in product.images that i want to show individually in the carousel but when i map them like this:
<AliceCarousel autoPlay autoPlayInterval="1500">
{[product.images].map((x) => (
<img src={x} alt={x} className="medium" />
))}
</AliceCarousel>
they do not show individually but all at once like so:
How would you map so as to get each url in the array individually to be shown within the carousel? Thanks
Probably OP resolved this by now, but if you have the responsive object then you can specify when to show how many elements you would like.
const responsive = {
2000: {
items: 10,
},
1200: {
items: 5,
},
800: {
items: 3,
},
0: {
items: 1,
},
};
<AliceCarousel responsive={responsive} autoPlay autoPlayInterval="1500">
{[product.images].map((x) => (
<img src={x} alt={x} className="medium" />
))}
</AliceCarousel>
In this scenario there would be 1 item from 0px width screen to 799px
Source: https://github.com/maxmarinich/react-alice-carousel

Adding an image and an anchor tag to an element within an array using props in React

While creating cards and using props in React.js I need to add an anchor tag(website:) and an image (image:) within a few elements in an array but am unable to figure out how. Of course, as seen below simply just adding an anchor tag etc does not work. Any help would be appreciated.
const projects = [
{
id: 1,
image: <img src="https://picture.jpg" alt="Coaching Website">
name: "Personal Coaching Website",
meaning:"A comprehensive website for a personal health and wellness coach"
website:
},
Rather than defining elements in an array, use the values, and map into the properties of the element.
const projects = [
{
id: 1,
image: "https://picture.jpg",
name: "Personal Coaching Website",
meaning: "A comprehensive website for a personal health and wellness coach",
website: "https://www.samplewebsite.com"
}
];
export default function App() {
return (
<div>
{projects.map(project => {
return (
<div>
<img src={project.image} />
<a href={project.website} />
</div>
);
})}
</div>
);
}

Resources