Add photo in object and show it - javascript

I need your help. I try to insert in an array with objects of a photo, to erase and then to deduce. I have no errors in the code, but instead of a photo it shows me a photo icon. All my photos are in a separate folder inside the src folder. Tell me if I'm doing it right or how do I insert a photo into the object and then erase it? Thank you very much
Pizza.js
export let pizza_description = [
{ id: 1,
title: 'title 1',
image: 'bavarska.jpg'},
{ id: 2,
title: 'title: 2',
image: 'salami.jpg'}
]
Pizza_page
import React, {useState} from "react";
import {pizza_description} from "../Food_description/Pizza/Pizza";
export let Pizza_page = () => {
let [pizza, different_pizza] = useState(pizza_description)
return (<div>
{pizza.map(el => <div key={el.id}>
<img key={el.id} src={el.image}/>
<h1>{el.title}</h1>
</div>)}
</div>)
}

You have to import the images or put them in the public directory then reference them like
return (<div>
{pizza.map(el => <div key={el.id}>
// assuming that el.image = image name + extension
<img key={el.id} src={`/pizPhotos/${el.image}`}/>
<h1>{el.title}</h1>
</div>)
}
</div>)
}

Related

Display image from another js file

I've got a problem with showing image from js file. I really dont know what i can do with that. Can someone help me?
Code for main component:
import React from 'react'
import {jetData} from '../jetData'
const MainBar = () => {
return (
<div className='text-white'>
{jetData.map((data, key) => {
return (
<div key={key}>
{<img src={data.image} /> + data.name}
</div>
);
})}
</div>
)
}
export default MainBar
Code for js file with data:
import f18 from './assets/jets/f-18cd-hornet.png'
import f22 from './assets/jets/f-22-raptor.png'
import mig29 from './assets/jets/mig-29.png'
import su27 from './assets/jets/Sukhoi_Su-27SKM.png'
export const jetData = [
{
image: {f18},
name: 'F/A-18 Hornet'
},
{
image: {f22},
name: 'F-22 Raptor'
},
{
image: {mig29},
name: 'MiG-29'
},
{
image: {su27},
name: 'Su-27'
},
]
Check if this works i hope it will work sorry at this point i can not run it for you
return (
<div className="text-white">
{jetData.map((jet) => (
<div key={jet.id}>
<img src={jet.image} alt={jet.name} />
</div>
))}
</div>
);
I think what you are trying to do is this:
import logo from './logo.svg';
<img src={logo} className="App-logo" alt="logo" />
Which works fine with .svg files, but not with .jpg and .png. The reason seems to be that import logo from './logo.svg'; stores the path in the variable, but import f18 from './assets/jets/f-18cd-hornet.png stores a, what to me looks like, a string representation of the image.
I think this is the way to go:
export const jetData = [
{
image: './assets/jets/f-18cd-hornet.png',
name: 'F/A-18 Hornet'
}]
Your imports do not need to be in curly braces:
import f18 from './assets/jets/f-18cd-hornet.png'
import f22 from './assets/jets/f-22-raptor.png'
import mig29 from './assets/jets/mig-29.png'
import su27 from './assets/jets/Sukhoi_Su-27SKM.png'
export const jetData = [
{
image: f18,
name: 'F/A-18 Hornet'
},
{
image: f22,
name: 'F-22 Raptor'
},
{
image: mig29,
name: 'MiG-29'
},
{
image: su27,
name: 'Su-27'
},
]
Your map key will likely throw an error because you are using the index as a key. I would change it to the following
{jetData.map((data) => {
return (
<div key={data.name}>
<img src={data.image} alt={data.name} />
</div>
);
})}

Image is not showing in React app using img tag

My image is not showing in React app. I am trying to fetch the path from JSON and pass the path using props in <img> tag.
Example JSON object with the product data:
let data = [
{
id: 1,
name: "Striped Slim Fit Shirt",
image: "./Assets/m1.jpg",
price: 1000,
category: "Men",
size: "XL",
inStock: true,
},
{
id: 2,
name: "Full Sleeves Slim Fit Shirt",
image: "./Assets/m2.jpg",
price: 2000,
category: "Men",
size: "L",
inStock: true,
},
];
export default data;
My parent component from which I am passing props.
import { Fragment } from "react";
import data from "../../DUMMY_DATA";
import ItemList from "./ItemList";
const HomePage = () => {
const availableItems = data.map((products) => (
<ItemList
key={products.id}
images={products.image}
name={products.name}
price={products.price}
category={products.category}
size={products.size}
/>
));
return (
<Fragment>
<div>{availableItems}</div>
</Fragment>
);
};
export default HomePage;
My child component. Here, console logging shows the correct path, but the <img> tag is not rendering it.
import { Fragment } from "react";
const ItemList = (props) => {
const { id, images, name, price, category, size, inStock } = props;
return (
<Fragment>
<div className="container text-center">
<div className="row row-cols-4" key={id}>
<div className="col">
<img src={images} />
</div>
<div className="col">{name}</div>
<div className="col">{size}</div>
<div className="col">{price}</div>
</div>
</div>
</Fragment>
);
};
export default ItemList;

importing image dynamically (React Js) (Require img path cannot find module)

I need to import images(several) from my image file dynamically by a map method. First, I want to set a base URL to my images file and then read the image's name from my JSON file which includes the image property and then set the image src accordingly.
The JSON file is like below :
{
"title": "Blue Stripe Stoneware Plate",
"brand": "Kiriko",
"price": 40,
"description": "Lorem ipsum dolor sit amet...",
"image": "blue-stripe-stoneware-plate.jpg"
},
{
"title": "Hand Painted Blue Flat Dish",
"brand": "Kiriko",
"price": 28,
"description": "Lorem ipsum dolor sit amet...",
"image": "hand-painted-blue-flat-dish.jpg"
},
my images folder :
I have read the products by redux which is works perfectly =>
const products = this.props.products;
console.log(products, 'from redux');
const fetchProducts = [];
for (let key in products) {
fetchProducts.push({
...products[key]
});
}
the console.log() =>
Now I want to define a base URL like this which later use as image src by adding the image's name from the JSON file in the map method :
const baseUrl = '../../components/assets/images/';
const fetchProducts = [];
for (let key in products) {
fetchProducts.push({
...products[key]
});
}
const productCategory = fetchProducts.map((product, index) => {
return (
<Photo
key={index}
title={product.title}
brand={product.brand}
description={product.description}
imageSource={baseUrl + product.image}
imageAlt={product.title}
/>
);
});
my Photo component looks like below :
const photo = props => (
<div className={classes.Column}>
<img src={require( `${ props.imageSource }` )} alt={props.imageAlt} />
<div className={classes.Container}>
<p>{props.brand}</p>
<p>{props.title}</p>
<p>{props.price}</p>
</div>
</div>
);
export default photo;
unfortunately, I have faced this error:
Thanks in advance and sorry for my bad English :)
Import is not working like that. You can use a base URL like that:
const baseUrl = "../../components/assets/images/";
Then you can pass to your Photo component like that:
<Photo
key={index} // Don't use index as a key! Find some unique value.
title={product.title}
brand={product.brand}
description={product.description}
imageSource={baseUrl + product.image}
imageAlt={pro.title}
/>;
Lastly, in your Photo component use require:
<img src={require( `${ props.imageSource }` )} alt={props.imageAlt} />
or like that:
<img src={require( "" + props.src )} alt={props.imageAlt} />
But, don't skip "" part or don't use it directly like:
<img width="100" alt="foo" src={require( props.src )} />
since require wants an absolute path string and first two do this trick.
Try this solution for dynamic image:-
**Componet**
const photo = props => (
<div className={classes.Column}>
<img src={require( `../../components/assets/images/${props.imageSource}`)} alt={props.imageAlt} />
<div className={classes.Container}>
<p>{props.brand}</p>
<p>{props.title}</p>
<p>{props.price}</p>
</div>
</div>
);
**Include Componet**
const productCategory = fetchProducts.map((product, index) => {
return (
<Photo
key={index}
title={product.title}
brand={product.brand}
description={product.description}
imageSource={product.image}
imageAlt={product.title}
/>
);
});
So here is what I found and it worked for me.
"file-loader": "4.3.0"
React: 16.12
Run this in your terminal:
npm run eject
Check file-loader in config/webpack.config and located file-loader configurations. What I did was, I created a directory called static/media/{your_image_name.ext} following the notation there:
options: {
name: "static/media/[name].[hash:8].[ext]"
}
and then imported this image like
import InstanceName from "static/media/my_logo.png";
Happy Hacking!
After trying all kinds of solutions, including backticks <img src={require( `${ props.imageSource }` )} and others, nothing was working. I kept getting the error Cannot find module, even though my relative paths were all correct. The only primitive solution I found, if you have a relatively small number of possible images, is to predefine a Map that will map to the actual imports. (Of course this won't work for lots of images.)
import laptopHouse from '../../images/icons/laptop-house.svg'
import contractSearch from '../../images/icons/file-contract-search.svg'
..
const [iconMap, setIconMap] = useState({
'laptopHouse': laptopHouse,
'contractSearch': contractSearch,
..
});
..
<img src={iconMap[props.icon]} />
i solved this typescript issue as follows in my project.
hope this is helpful
export const countryData = {
'sl': { name: 'Sri Lanka', flag: '/flag-of-Sri-Lanka.png' },
'uk': { name: 'UK', flag: '/flag-of-United-Kingdom.png' },
'usa': { name: 'USA', flag: '/flag-of-United-States-of-America.png' },
'ca': { name: 'Canada', flag: '/flag-of-Canada.png' },
'It': { name: 'Italy', flag: '/flag-of-Italy.png' },
'aus': { name: 'Australia', flag: '/flag-of-Australia.png' },
'me': { name: 'Middle East', flag: '/flag-of-Middle-East.png' },
'other': { name: 'Other', flag: '/flag-of-World.png' }, };
"part of URL within Double quotes" + dynamic_URL_via_var combo worked for me.
<Avatar src={require('../assets'+countryData['uk']['flag'])} />
//json data.
"ProductSlider":[
{
"image":"Product1.jpg"
},
{
"image":"Product2.jpg"
}]
//mapping data list in parent component.
{sliderData.map((data) => (
<SwiperSlide className='w-10 '>
<ProductCard data={{imgSrc: data.image}} />
</SwiperSlide>
))}
//child component(linked image).
import React from 'react'
import { CardImg } from 'react-bootstrap'
export default function ProductCard(props) {
let {imgSrc} = props.data;
return (
<div className="overflow-hidden">
<div className='overflow-hidden bg-grey opacity-card' >
<CardImg
variant='top'
src={require(`../assets/images/${imgSrc}`)}
/>
</div>
<div className='text-center p-1 opacity-card-title' >
<div>Add to cart</div>
</div>
</div>
)
}
Even I got the same error
{gallery.map((ch, index) => {....
cannot find module '/../..................png'
I went wrong here, I used src instead of ch
Error
<Image src={src.image} />
Solved
<Image src={ch.image} />

changing image source by dealing with state in Reactjs

I am trying to make an Image slider like e-commerce product in Reactjs.
In javascript it's pretty simple, we only need to change the image source, but how to do it in React? because in React we have to deal with state.
First I mapped out all four images(state) as side images(className ='sideImages') then hardcoded the first image of state as display image. Now I want when I click any of the side images it becomes display image (className='display')
I hope I am clear.
Here is my component
import React, { Component } from 'react';
class App extends Component {
state = {
images: [
{
id: 1,
img: "https://images.pexels.com/photos/1"
},
{
id: 2,
img: "https://images.pexels.com/photos/2"
},
{
id: 3,
img: "https://images.pexels.com/photos/3"
},
{
id: 4,
img: "https://images.pexels.com/photos/4"
}
]
};
onClickHandler = () => {
this.setState({
// this.state.images[0]['img']: 'this.src'
})
}
render() {
const sideImages = this.state.images.map(image => (
<img key={image.id} src={image.img} alt="" />
));
return (
<div className="imageSlider">
<div onClick={this.onClickHandler} className="sideImages">
{sideImages}</div>
<div className='display'>
<img src={this.state.images[0]['img']} alt="" />
</div>
</div>
)
}
}
export default App;
You can take another/better approach of doing this.
Keep 2 variables in your state i.e. image array [don't mutate it] and selectedImageIndex to keep track of currently selected/clicked thubnail.
Whenever you click on any thumbnail image, just change the selectedImageIndex and the target image src can point to <img src={this.state.images[this.state.selectedImageIndex]["img"]} alt="" />
Here is the working example: https://codepen.io/raviroshan/pen/QVraKo

Rendered HTML not in sync with React component

I'm currently creating a custom React component in Meteor for adding images to a list (and later uploading them). However when I try to delete images from the list, always the last element is removed from the GUI. Initially I thought this was just a simple case of using the wrong index for deletion, but it turned out to be more than that.
This is what my ImageList component currently looks like:
import React from 'react';
import Dropzone from 'react-dropzone';
import cloneDeep from 'lodash.clonedeep';
import { ImageItem } from './image-item.js';
export class ImagesList extends React.Component {
constructor(props) {
super(props);
this.values = this.props.images || [];
this.onDrop = this.onDrop.bind(this);
this.addImages = this.addImages.bind(this);
this.deleteImage = this.deleteImage.bind(this);
this.imageChanged = this.imageChanged.bind(this);
}
onDrop(files) {
this.addImages(files);
}
onDropRejected() {
alert('Invalid file type');
}
addImages(files) {
files.forEach(file => {
this.values.push({
title: '',
description: '',
url: file.preview,
file,
});
});
this.forceUpdate();
}
deleteImage(index) {
console.log('index to delete', index);
console.log('images pre-delete', cloneDeep(this.values)); // deep-copy because logging is async
this.values.splice(index, 1);
console.log('images post-delete', cloneDeep(this.values)); // deep-copy because logging is async
this.forceUpdate();
}
imageChanged(index, image) {
this.values[index] = image;
this.forceUpdate();
}
render() {
console.log('--------RENDER--------');
return (
<div className="image-list">
<div className="list-group">
{this.values.length === 0 ?
<div className="list-group-item">
No images
</div>
:
this.values.map((image, index) => {
console.log('rendering image', image);
return (
<ImageItem
key={index}
image={image}
onDelete={() => { this.deleteImage(index); }}
onChange={(item) => { this.imageChanged(index, item); }}
deletable={true}
/>
);
})
}
</div>
<Dropzone
multiple={true}
onDrop={this.onDrop}
onDropRejected={this.onDropRejected}
className="dropzone"
activeClassName="dropzone-accept"
rejectStyle={this.rejectStyle}
accept={'image/*'}
>
<span>Drop files here</span>
</Dropzone>
</div>
);
}
}
The ImagesList component can be initialized with some values (for the sake of debugging), which it uses during rendering. For example:
<ImagesList images={[
{ title: 'Image 1', description: 'Image 1 description', url: 'http://cssdeck.com/uploads/media/items/3/3yiC6Yq.jpg' },
{ title: 'Image 2', description: 'Image 2 description', url: 'http://cssdeck.com/uploads/media/items/4/40Ly3VB.jpg' },
{ title: 'Image 3', description: 'Image 3 description', url: 'http://cssdeck.com/uploads/media/items/0/00kih8g.jpg' },
]}/>
ImagesList renders an ImageItem component for each image. This is what this component looks like:
import React from 'react';
import { RIEInput, RIETextArea } from 'riek';
export class ImageItem extends React.Component {
constructor(props) {
super(props);
this.placeholder = {
title: 'Title',
description: 'Description',
};
this.value = this.props.image;
}
render() {
return (
<div className="list-group-item">
<div className="text-content">
<h4>
<RIEInput
className="description"
value={this.value.title.length <= 0 ?
this.placeholder.title : this.value.title}
change={(item) => {
this.value.title = item.value;
this.props.onChange(this.value);
}}
validate={(value) => value.length >= 1}
classEditing="form-control"
propName="value"
/>
</h4>
<span>
<RIETextArea
className="description"
value={this.value.description.length <= 0 ?
this.placeholder.description : this.value.description}
change={(item) => {
this.value.description = item.value;
this.props.onChange(this.value);
}}
validate={(value) => value.length >= 1}
classEditing="form-control"
propName="value"
rows="2"
/>
</span>
</div>
<img className="thumb img-responsive"
style={{width: '20%' }}
src={this.value.url}
alt="Image"
data-action="zoom"
/>
{this.props.deletable ?
<div className="delete-btn">
<span onClick={this.props.onDelete}>
×
</span>
</div>
:
undefined }
</div>
);
}
}
Let's say I have three images, image A, B and C, and I want to delete image B. After pressing the delete button, image C will disappear from the GUI instead.
Inside the deleteImage() function of ImagesList, I am logging the index that is to be deleted and also log the values before and after the deletion. The index that is logged is correct, in this case that is index 1. Before the deletion the values are images A, B and C. After deletion the values are images A and C, as they should be.
I decided to do some logging inside the render() function of ImagesList as well. Unfortunately this also logs the correct values A and C, but A and B are actually rendered.
I have also tried to use the React state for this component instead of storing it in a local variable in conjunction with forceUpdate().
Another thing I have tried is to use the React Developer Tools plugin for Chrome. The Devtools also show the correct values, but the GUI still does not, as shown in this screenshot.
I'm currently out of ideas on what to try, any help would be appreciated!
Using the snippets I provided, you should be able to create a Meteor project and reproduce this bug.
With MasterAM's suggestion I managed to find two different solutions.
A.) Using componentWillUpdate()
The this.value variable is set only once namely in the constructor of the ImageItem component. To ensure that changes are properly delegated, you have to update this.value inside the componentWillUpdate() function. Something like:
componentWillUpdate(nextProps, nextState) {
this.value = nextProps.image;
}
B.) Using the property directly
This is definitely the more proper solution. Here we get rid of the local variable this.value inside the constructor of the ImageItem component.
Inside the render() function you replace this.value with this.props.image. Now without having to use the componentWillUpdate() function, everything works as expected.

Categories