failed to get img displayed using forEach in react - javascript

I want to render image from my api, I first used size of lodash to check the array is empty or not, if it's empty display the upload button, else just render the images.
When I do
{item.photos.toString()} I'm able to see the url but why below code just doesn't work? no error at all in my console.
<div id="photo_upload">
{size(item.photos) > 1 ?
item.photos.forEach(photo =>{
<img src={photo} />
})
: <div><button>Upload</buton>
</div>}
</div>

You use condition size(item.photos) > 1 only so it won't show if you have only 1 photo.
Another thing is you should add key for each element while doing the loop
item.photos.forEach(photo =>{
<img key={photo} src={photo} />
})

forEach doesn't return anything, so that operand in your conditional will have the value undefined. You wanted map (and return inside it). Also note your closing button tag for the Upload button is missing a t (fixed below):
<div id="photo_upload">
{size(item.photos) > 1 ?
item.photos.map(photo =>{
return <img src={photo} />;
})
: <div><button>Upload</button>
</div>}
</div>
You can also use the concise arrow form:
<div id="photo_upload">
{size(item.photos) > 1 ?
item.photos.map(photo => <img src={photo} />)
: <div><button>Upload</button>
</div>}
</div>
Adding in the points raised by Đào Minh Hạt in his answer (> 0 rather than > 1, and key):
<div id="photo_upload">
{size(item.photos) > 0 ?
item.photos.map(photo => <img key={photo} src={photo} />)
: <div><button>Upload</button>
</div>}
</div>

Related

Display image from .map array (React)

setForecast(res2.data.list.map(item => [
<div className="each_data_point">
<li className="date_time" key={item.dt_txt}>{`Date & Time: ${item.dt_txt}`}</li>,
<img className="icon" key={item.weather[0].icon}>{`https://openweathermap.org/img/w/${item.weather[0].icon}.png`}</img>,
<li className="main_temp" key={item.main.temp}>{`Temp: ${item.main.temp}`}</li>
</div>
]
))
......
return (
<div>
<div className="five_day_forecast">
<div className="temp_body">
// Display here with Date/Time & Main Temp.
<p>{forecast}</p>
</div>
</div>
Is it possible to render an image from array.map() within React. When I run this, the DOM clears completely to white screen.
Using src in the img tag to render image
<img className="icon" key={item.weather[0].icon} src={`https://openweathermap.org/img/w/${item.weather[0].icon}.png`} />
And put the key in div instead in the children.
Not sure why you are doing it, but setting JSX in your state seems strange.
Try something like this, assuming res2.data.list has the list of values.
<div className="five_day_forecast">
<div className="temp_body">
// Display here with Date/Time & Main Temp.
<p>
{res2.data.list && res2.data.list.length >0 && res2.data.list.map(item => [
<div className="each_data_point">
<li className="date_time" key={item.dt_txt}>{`Date & Time: ${
item.dt_txt
}`}</li>
,
<img
className="icon"
key={item.weather[0].icon}
>{`https://openweathermap.org/img/w/${
item.weather[0].icon
}.png`}</img>
,
<li className="main_temp" key={item.main.temp}>{`Temp: ${
item.main.temp
}`}</li>
</div>
])}
</p>
</div>
</div>
Putting markup in state is a weird anti-pattern. State is really there to just store data not markup. You can use a function to create the JSX from mapping over the data.
You should be adding the source of the image to the src attribute of the img element.
Keys should be added to parent elements.
const imgSrc = `https://openweathermap.org/img/w/${item.weather[0].icon}.png`;
<img src={imgSrc} />
// `fetch` your data, and add it to state
setForecast(res2.data.list);
// `map` over the data and create the markup
function getMarkup() {
const imgSrc = `https://openweathermap.org/img/w/${item.weather[0].icon}.png`;
return forecast.map(item => {
<div className="each_data_point" key={item.dt_txt}>
<li className="date_time">{`Date & Time: ${item.dt_txt}`}</li>,
<img src={imgSrc} className="icon" />,
<li className="main_temp">{`Temp: ${item.main.temp}`}</li>
</div>
});
}
return (
<div>
<div className="five_day_forecast">
<div className="temp_body">
// Call the function to return the markup
// build from state
{getMarkup()}
</div>
</div>
);

Conditional class style binding in Vue.js

I want to make that styles are added to images only under a certain condition.
Here is code:
<div>
<div v-for="(item, index) in productsList" :key="item.id" class="cart-img">
<img
v-if="item.file"
:src="
`https://server.com/${
index === productsListBigIndex ? item.fileWide : item.file
}`
"
:alt="item.altText || item.text"
draggable="false"
/>
<img
v-else
:alt="item.altText || item.text"
:src="'https://server.com/empty.png'"
/>
<p style="font-size: medium">{{item.text}}</p>
</div>
</div>
The style should depend on the index and productsListBigIndex. For example, if the index is 0 or 2, then this style (in particular the size of the picture) will be added, otherwise it will not.
Thanks for answers!
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
Like this you can conditionally add or remove a classname and styles specified,
v-bind:class="getClass()"
methods:{
getClass(){
//logic to check the condition and return the class name
}
}

Load img tag source before css is applied in Reactjs

I want to input a picture in my Lightbox, but from what I see the problem is that the CSS is applied before the img source can be loaded inside of the tag
Problem: The Lightbox Activates without an image source.
It only works if I put an img source manually.
class LightboxTest extends Component {
state = {};
render() {
return (<React.Fragment>
<div
className={this.props.setActivity === false ? 'lightboxOff' : this.props.setActivity === true ? 'lightboxActive' : ''}
>
<img alt="" src={this.props.lbImages} />
</div>
</React.Fragment>);
}
}
export default LightboxTest;
I'm passing a boolean 'setActivity' per props to check whether an image has been clicked on to set the Lightbox Active and 'lbImages' as my source which should be loaded, when clicked on an image.
<div className="header">
{images.map((image) => (
<React.Fragment key={image.id}>
<img
alt=""
src={image.src}
key={image.id}
onClick={() => {
setLightboxImage(image.src);
}}
onClick={handleClick}
/>
</React.Fragment>
))}
</div>
When I remove the lightbox div tag the image appears with no issue when Clicked on.
Can I set like a priority?
you have two onClick handlers, so the second one isn't executed. Can be changed to:
onClick={() => {
setLightboxImage(image.src);
handleClick();
}}

How to check condition inside map without putting a div

I am trying to put a "col-sm-6" inside a row with checking a condition . But when null value is coming it is returning a blank div with ".col-sm-6" class, I need to hide that class when value is null.
<div className="row">
{attribute.attributeValues.map((list, index) =>
<div className="col-sm-6" >
{list.isSelected === 1 ?
<div className="style">
<span><i className="fa fa-check"></i>{list.tag_value}</span>
</div>:''
}
</div>
)}
</div>
this is giving results like:
like:
<div class="row">
<div class="col-sm-6">Some Value</div>
<div class="col-sm-6"></div>
<div class="col-sm-6"></div>
</div>
But I want:
<div class="col-sm-6">Some Value</div>
<div class="col-sm-6">Some Value</div>
<div class="col-sm-6">Some Value</div>
You can make use of React.Fragment like
<div className="row">
{attribute.attributeValues.map((list, index) =>
<React.Fragment key={index}>
{list.isSelected === 1 ?
<div className="style">
<span><i className="fa fa-check"></i>{list.tag_value}</span>
</div>:''
}
</React.Fragment>
)}
</div>
According to the docs:
A common pattern in React is for a component to return multiple
elements. Fragments let you group a list of children without adding
extra nodes to the DOM.
Second method to remove the wrapping {} in the ternary condition
<div className="row">
{attribute.attributeValues.map((list, index) =>
list.isSelected === 1 ?
<div className="style">
<span><i className="fa fa-check"></i>{list.tag_value}</span>
</div>: null
)}
</div>
Actually, you just need to use filter (MDN documentation) before the map. You can do something like:
attribute.attributeValues.filter(list => list.tag_value).map(...
That way, with filter, you return a new Array in which only items with a "real" list.tag_value value.
In JavaScript, everything without a "Value" is False (JavaScript Booleans). That means that the filter above will filter out any list.tag_value equal to: undefined, null, empty String ("") or Number equal to 0.

How to skip first in map function

I want to skip the first in the .map function what I do now is this:
block.gallery.map((item, i) => (
<div className="gallery-item" key={i}>
{ block.gallery.length > 4 && i !== 0 ?
<div className="inner">
<img src={block.gallery[i].images.thumbnail_sm} alt={block.title} srcSet={`${block.gallery[i].images.thumbnail_md} 1x, ${block.gallery[i].images.thumbnail_lg} 2x`} className="img-fluid" title="" />
<div className="img-overlay">
<span className="img-overlay-body">{ block.gallery.length - 4 }+ <span className="hidden-xs">Foto's</span></span>
</div>
</div>
:
<img src="http://placehold.it/800x538" alt="" className="img-fluid" title="" />
}
So slice it to skip the first
block.gallery.slice(1).map(...)
You also need to reference the item passed into map, not using the index with the orginal array.
block.gallery[i].images.thumbnail_sm
should be
item.images.thumbnail_sm
You can also remove the first element, and retrieve it at any point, using Array.prototype.shift(); however, this modifies the original array.
const head = block.gallery.shift(); // removes and stores first element in "head"
console.log(block.gallery) // array with first element removed

Categories