How to skip first in map function - javascript

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

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>
);

Is there a way to add the attribute loading="lazy" only in certain conditions?

I am using the relativly new HTML attribute loading="lazy". I only want it to be enabled when the number of images rendered on the page excedes 10. I am building my website using Vue.js v3. I am loading the images with a v-for card like this:
<div
class="gallery-panel"
v-for="photo in filteredPhotos"
v-bind:key="photo.id"
:class="`${photo.display}`"
>
<a #click="this.$router.push(`/Album/${album}/Photo/${photo.id}`)">
<img
loading="auto"
v-bind:src="thumbUrl(photo.filename, album)"
v-bind:alt="`${photo.filename}`"
/>
</a>
</div>
Where filteredPhotos is an array with image information from a JSON file.
Is there a way to change the loading="auto" to loading="lazy" when the number of photos is going to be more than 10?
Well, you can simply add an index attribute to your v-for to check whether the length of your array exceeding 10 or not (Since the index will begin from 0 you should set your condition to > 9). Then you can make your loading attribute conditional like this:
<img :loading="index > 9 ? 'lazy' : 'auto'" />
So your final code should be something like this:
<div class="gallery-panel" v-for="(photo, index) in filteredPhotos" v-bind:key="photo.id" :class="`${photo.display}`">
<a #click="this.$router.push(`/Album/${album}/Photo/${photo.id}`)">
<img :loading="index > 9 ? 'lazy' : 'auto'" v-bind:src="thumbUrl(photo.filename, album)" v-bind:alt="`${photo.filename}`" />
</a>
</div>
You can use index of v-for e.g
<div
class="gallery-panel"
v-for="(photo, index) in filteredPhotos"
v-bind:key="photo.id"
:class="`${photo.display}`"
>
<a #click="this.$router.push(`/Album/${album}/Photo/${photo.id}`)">
<img
:loading="index > 9 ? 'lazy' : 'auto'"
v-bind:src="thumbUrl(photo.filename, album)"
v-bind:alt="`${photo.filename}`"
/>
</a>
</div>

How do I highlight 1 image at a time in an image gallery using react or css

I'm creating an image selection modal, and want the user to only choose 1 image. I know how to get that unique image and push that data, but I don't know how to highlight one individual image at a time.
For example, if the user clicks on 1 image that image should have a blue border around it, but if they click on another image, then the 2nd image will have a blue border and the other image will lose that border.
There could potentially be hundreds of images, so I can't write it out by hand. How can I do this?
Here's some of my code, pretty basic stuff.
imageChosen = (e) => {
console.log(e)
};
<div className={classes.imageList}>
<div className={classes.imageWrap}>
<img onClick={(e) => this.imageChosen(e.target.src)} src="smallfamilyadv.jpg" alt="" />
</div>
<div className={classes.imageWrap}>
<img onClick={(e) => this.imageChosen(e.target.src)} src="BugzPlaypark.jpg" alt="" />
</div>
<div className={classes.imageWrap}>
<img onClick={(e) => this.imageChosen(e.target.src)} src="play-park-500x500.jpg" alt="" />
</div>
</div>
Use a state, and an array list
state = {
imageChosen : undefined;
}
render() {
const img = ["smallfamilyadv.jpg","BugzPlaypark.jpg", "play-park-500x500.jpg"]
return <div className={classes.imageList}>
{img.map((e,i)=> {
return <div key={i} className={this.state.imageChosen === e ? classes.imageWrapSelected : classes.imageWrapNormal}>
<img onClick={(e) => this.setState({imageChosen:e.target.src})} src={e} alt={e} />
</div>
})}
</div>
}

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.

failed to get img displayed using forEach in react

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>

Categories