Broken icon is displayed for the image with alt text - javascript

I have an image called image.jpg inside the src -> images -> image.jpg. I have some problem with my image on my React app. My code is running well but the image does not show up instead on saving and loading the application, the image is not displayed but broken icon is displayed with alt text. How is it possible to solve this problem?
What I have tried is:
import React from "react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
term: "",
names: [
{ name: "Deepak", job_profile: "Quality Analyst", description: "He is Passionate in Tester" },
{ name: "Deepinder", job_profile: "iOS Developer", description: "He is a Dedicated iOS Developer" }
],
filteredData: [{}]
};
}
render() {
let terms = "";
if (this.state.term) {
terms = this.state.term.toLowerCase();
}
return (
<div className="App">
<label>Search Employee: </label>
<input
type="text"
value={this.state.term}
id="searchEmp"
placeholder="Enter Name"
onChange={(event) => {
if (event.target.value.indexOf(" ") > -1) {
alert("Please don\'t enter space.");
this.setState({ term: "" });
return;
}
this.setState({ term: event.target.value });
}}
/>
<br />
<br />
{this.state.names &&
this.state.names
.filter((x) => x.name.toLowerCase().startsWith(terms) || (x.description.toLowerCase().includes(terms)))
.map((item) => {
return (
<div className="data-body">
<div>Name : {item.name}</div>
<div>Job Profile : {item.job_profile}</div>
<div>Description : {item.description}</div>
<div><img src={require('../src/images/image.jpg')} alt="profile_picture" /></div>
<input type="button" id="button"
value="Delete" onClick={() => {
this.setState
({ names: this.state.names.filter
(i => i.name !== item.name) });
}}/>
<div>{<br></br>}</div>
</div>
);
})}
</div>
);
}
}
export default App;

I assume that you are using create-react-app to bundle your project. If that is the case, you just need to put all your images in the public folder and just mention the name in the src attribute.
You don't need the require function while mentioning the source of an image.
So, your code should look like this:
<img src="image.jpg" alt="profile_picture"/>
If you want the image to reside in some part of your source directory, you can import the image from there and use it in your code as follows:
import Image from '../images/image.jpg'
<img src={Image} alt="profile_picture"/>
Edit
Using ES5 syntax, you could do the following:
const Image = require("../images/image.jpg")
<img src={Image} alt="profile_picture"/>

i hope this helps you
<div>
<img src='../src/images/image.jpg' alt="profile_picture" />
</div>

Related

Pre-populate image field in the React js form

I am new in reactjs. i am trying to update the form. Everything is pre-populating except for image field. So I have displayed image on current image label.
as because image field is not pre-populating, due to this filling up the image have become mandatory.
below is the code
import React, { Component } from 'react';
import axios from 'axios';
import './updateitem.css';
import { Link } from 'react-router-dom';
class updateItem extends Component{
constructor(props){
super(props);
this.state = {
name: '',
description: '',
price: '',
image: '',
message: "",
id: '',
image_to_display: '',
}
}
componentDidMount(){
const itno = this.props.match.params.itno;
const itemAPI = `${window.apiHost}/api/items/${itno}`;
axios.get(itemAPI).then(res => {
this.setState({
name: res.data.result.item_detail.name,
description: res.data.result.item_detail.description,
price: res.data.result.item_detail.price,
image: res.data.result.item_detail.image,
id: res.data.result.item_detail.id,})
})
}
onImageChange= (event)=>{
this.setState({
'image': event.target.files[0],
})
}
handleChange= (event)=>{
this.setState({
[event.target.name]: event.target.value,
})
}
handleUpdate = async (event)=>{
console.log('handle update');
const itno = this.props.match.params.itno;
const itemAPI = `${window.apiHost}/api/items/${itno}/`;
event.preventDefault();
let form_data = new FormData();
form_data.append('name', this.state.name);
form_data.append('description', this.state.description);
form_data.append('price', this.state.price);
form_data.append('image', this.state.image, this.state.image.name);
await axios.put(itemAPI,
form_data, {headers: {
'content-type': 'multipart/form-data'
}}).then(res => {
this.setState({
name: res.data.result.item_detail.name,
description: res.data.result.item_detail.description,
price: res.data.result.item_detail.price,
image: res.data.result.item_detail.image,
id: res.data.result.item_detail.id,
message: res.data.result.message})})
document.getElementById('update_message').innerHTML = this.state.message
}
render(){
return(
<div className="main_div">
<div className="title">
<h1>Welcome to "Sadguru's Amrit-Tulya-Tea Shop"</h1>
</div>
<div id="update_message"></div>
<div className='container con_class'>
<form onSubmit={this.handleUpdate} encType="multipart/form-data" className='update_form'>
<h2>Update Form</h2>
<div className="body">
<div className="name"><p>Name:</p><input type="text" value={this.state.name} onChange={this.handleChange} name="name"></input></div ><br></br>
<div className="desc"><p>Description: </p><textarea type="textarea" value={this.state.description} onChange={this.handleChange} name="description"></textarea></div><br></br>
<div className="price"><p>Price: </p><input type="text" value={this.state.price} onChange={this.handleChange} name="price"></input></div><br></br>
<div className="img"><p>Image: </p><input type="file" className="form-control" id="image" onChange={(e)=>this.onImageChange(e)} name="image" /></div>
<div className="_ext_img">Current Image<img src={this.state.image} alt="Card"/></div>
</div>
<div className="footer">
<button type="submit" className="btn btn-success update" >Update</button>
<Link to={`/items/${this.state.id}/`}>
<button type="button" className="btn btn-danger" >Cancel</button>
</Link>
</div>
</form>
</div>
</div>
)
}
}
export default updateItem;
if i am filling up the form then it gets updated.
i want the image to be prefilled with the data coming from API. and filling up the image should be optional. if user is not filling it up, than same image should be updated.
Please help me on this.
thanks in advance.
You can't have a default value for the file input. This is purposely done for security reasons, otherwise you could upload and submit a malicious file without the user's knowledge.
What you could do instead is work around this issue, e.g. the field doesn't need to be mandatory but you can have a default value for the image in your component's state, and simply add a message (and probably display the image) for the user below the form, that if no file is uploaded, the default one will be used.
It is not possible to pre-fill a file input, an uploaded file has to be selected by user manually. Besides, your API is most likely returns an image url, but file's input value is always a File instance.

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} />

React - one event handler to toggle one of multiple similar elements

I'm trying to practice React by rebuilding an agency website. I'm working on a section which has staff images, and clicking one of those images opens the relevant staff bio in a modal. The images and the bios are in separate containing divs.
It feels like I should be able to write one event handler that finds and opens the relevant bio depending on which image is clicked (maybe using something like the data attribute?), but I can't figure out what I'd need to add.
Currently I just have a click handler which toggles a piece of 'active' state. That state is then added as a className to toggle whether the modal is showing. Problem of course being that it doesn't differentiate between bios, so they all show regardless which bio is clicked on.
In case it's useful, here is my 'staff bio' component:
const StaffBio = (props) => {
return (
<div className={`teamMemberOverlay ${props.active}`} onClick={props.onClick}>
<div className="teamMemberExpanded">
<h6>{props.name}</h6>
<div className="seperator"></div>
<p className="title">{props.title}</p>
</div>
</div>
);
}
Which is being used like this:
<StaffBio name="NAME HERE" title="TITLE HERE" active={this.state.active} onClick={this.showBio} />
So far I've got the images set up as follows:
<img src={PaulIllustration} className="staffPhoto" onClick={this.showBio} />
And lastly, my event handler:
showBio() {
let toggle = this.state.active === 'is-active' ? '' : 'is-active';
this.setState({active: toggle});
}
class AboutUsSlider extends Component {
constructor(props) {
super(props);
this.showBio = this.showBio.bind(this)
this.next = this.next.bind(this)
this.state = { active: null }
}
next() {
this.refs.slider.slickNext()
}
showBio(id) {
this.setState({active: id});
}
hideBio(){
this.setState({active: null});
}
render() {
var settings = {...}
const people = [{name: 'Paul', title: 'some title'}, {name: 'Ben', title: 'other'}, ...];
return (
<div>
<Slider ref="slider" {...settings}>
<div className="sliderPage">
<h2>Meet our team</h2>
<div className="seperator"></div>
<div className="teamPhotos">
{ // When setting the index, you should use something unique, I'll use the name here.
people.map((p, index) =>
<img key={p.name} src={`${p.name} + 'Illustration'`} className="staffPhoto" onClick={() => this.showBio(index)}) />
}
</div>
<Button BGColor="#009ECC" text="Our process" onClick={this.next} />
</div>
</Slider>
{ this.state.active && <StaffBio name={people[this.state.active]} title={people[this.state.active].title} onClick={this.hideBio}/>
</div>
)
}
EDITED
There are a couple of things you can do.
Each person probably has an id to identify it. So you could modify your showBio to look like this:
showBio(id) {
this.setState({ active: id })
}
This way, you get which person is currently active in your state.
You also need to change your img
<img src={PaulIllustration} className="staffPhoto" onClick={() => this.showBio(PaulId)} />
Where PaulId would be different for each person.
And your StaffBio:
<StaffBio name="NAME HERE" title="TITLE HERE" active={this.state.active == personId} onClick={this.showBio} />
const StaffBio = (props) => {
return (
<div className={`teamMemberOverlay ${props.active ? 'is-active' : ''}`} onClick={props.onClick}>
<div className="teamMemberExpanded">
<h6>{props.name}</h6>
<div className="seperator"></div>
<p className="title">{props.title}</p>
</div>
</div>
);
}

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.

populating list item through json object reactjs

i have a json file that i fetch from a url then i put this object into a state variable, then when the user enters a city name in the search bar i fetch what the user entered and comapre it to my object's row location_city and then populate the card item accordingly, but the showResult function is not working for some reason and i can not figure it out, and when i press the button it keeps logging to the console the object fetched
update: it started magically working without me actually doing anything, there might have been a lagging problem or something, but anyway i still have the thread up because i would love if someone could tell me how i can implement the search function better and actually be able to populate more than one list item, and also if someone could help me make the slider navigation better , like when you click next on the last picture it goes to the first one and vice versa
import React from 'react';
import Card from './Card.js';
export default class Slider extends React.Component {
constructor() {
super()
this.state = {
imgArray: [ "/img/work1.jpg", "/img/work2.jpg", "/img/work3.jpg"],
imgNo: 0,
price: null,
location: null,
image: null,
name: null,
score: null,
url: "https://www.deskbookers.com/nl-nl/sajax.json?q=Amsterdam&type=-&people=any&favorite=0&pid=&sw=52.293753%2C4.634942&ne=52.455562%2C5.162286&ids=17201%2C19640%2C13692%2C13691%2C12136%2C17938%2C15292%2C14886%2C14885%2C14884%2C14883%2C15730%2C15353%2C15351%2C15330%2C15080%2C17290%2C15454%2C15451%2C15379",
current: "/img/work1.jpg",
search: null,
resultObject: null,
headlines: ["Pink Floyd Office", "Led Zeppelin Mania", "Central Perk Friends"],
headline : "Pink Floyd Office"
};
}
componentDidMount(){
this.serverRequest = $.get(this.state.url, function(result){
var info = result;
console.log(info);
this.setState({
resultObject:info
})
}.bind(this));
}
nextImg(){
if(this.state.imgNo < 2 && this.state.imgNo >=0 ){
this.setState({
imgNo : ++this.state.imgNo ,
current: this.state.imgArray[this.state.imgNo],
headline: this.state.headlines[this.state.imgNo]
})
console.log(this.state.imgNo);
}
}
prevImg(){
if(this.state.imgNo >= 1 && this.state.imgNo < 3 ){
this.setState({
imgNo : --this.state.imgNo,
current: this.state.imgArray[this.state.imgNo],
headline: this.state.headlines[this.state.imgNo]
})
console.log(this.state.imgNo);
}
}
searchQuery(){
this.setState({
search: this.refs.searchValue.value
})
}
showResult(){
var i;
for(i = 0; i<this.state.resultObject.rows.length; i++){
if(this.state.search == this.state.resultObject.rows[i].location_city){
this.setState({
price: this.state.resultObject.rows[i].day_price,
location: this.state.resultObject.rows[i].location_city,
image: this.state.resultObject.rows[i].image_urls2[0],
name: this.state.resultObject.rows[i].location_name,
score: this.state.resultObject.rows[i].location_rating
})
}
}
}
render(){
return(
<div>
<div class="slider ">
<div class="img-container">
<img src={this.state.current} class="main-img" />
<div class="headline"><span>{this.state.headline}</span></div>
</div>
<img src="/img/slider-left.png" class="slider-arrow" onClick={this.prevImg.bind(this)} />
<img src="/img/slider-right.png" class="slider-arrow slider-right" onClick={this.nextImg.bind(this)} />
<div class="search-container">
<input onChange={this.searchQuery.bind(this)} type="text" ref="searchValue" name="search" placeholder="City name..." class="search-bar" />
<button onClick={this.showResult.bind(this)} class="search-button">Sit me!</button>
</div>
</div>
<ul class="card-list">
<Card price={this.state.price} location={this.state.location} image={this.state.image}
score={this.state.score} name={this.state.name}>
</Card>
</ul>
</div>
);
}
}

Categories