building this lightbox in React, the problem I am facing is that when I goto the next image in the array, it's empty and just showing "Object object" as the error. I am grabbing both the image and text from the array of objects. Anyone have any ideas? The showNext() function is where it's not working. Thanks
import { useState } from 'react';
import Ant from '../../img/ant.jpeg';
import Bee from '../../img/bee.jpeg';
import Bedbug from '../../img/bedbug.jpeg';
import Wasp from '../../img/wasp.jpeg';
import Mouse from '../../img/mouse.jpeg'
// const images = [Bee, Ant, Bedbug, Wasp, Mouse];
const images_arr = [
{ image: Ant, text: "Ant" },
{ image: Bee, text: "Bee" },
{ image: Bedbug, text: "Bedbug" },
{ image: Mouse, text: "Mice" },
{ image: Wasp, text: "Wasp" },
]
function PestsGallery() {
const [imageToShow, setImageToShow] = useState({});
const [lightboxDisplay, setLightBoxDisplay] = useState(false);
//looping through our images array to create img elements
const imageCards = images_arr.map(({ image, text }) => (
<>
<span>{text}</span>
<img key={image} alt={image} className="image-card" onClick={() => showImage(image)} src={image} />
</>
));
//function to show a specific image in the lightbox, amd make lightbox visible
const showImage = (image) => {
setImageToShow(image);
setLightBoxDisplay(true)
}
//hide lightbox
const hideLightBox = () => {
setLightBoxDisplay(false)
}
//show next image in lightbox - this is where the error is happening, when i clicke the arrow the next image is empty.
const showNext = (e) => {
e.stopPropagation();
let currentIndex = images_arr.indexOf(imageToShow);
if (currentIndex >= images_arr.length - 1) {
setLightBoxDisplay(false)
} else {
let nextImage = images_arr[currentIndex 1];
setImageToShow(nextImage)
}
}
const showPrev = (e) => {
e.stopPropagation();
let currentIndex = images_arr.indexOf(imageToShow);
if (currentIndex <= 0) {
setLightBoxDisplay(false);
} else {
let nextImage = images_arr[currentIndex - 1];
setImageToShow(nextImage);
}
};
return (
<>
<h2> Bugs we treat</h2>
<div>{imageCards}</div>
{
lightboxDisplay ?
<div id="lightbox" onClick={hideLightBox}>
<button onClick={showPrev}>⭠</button>
<img alt="gallery" id="lightbox-img" src={imageToShow}></img>
<button onClick={showNext}>⭢</button>
</div>
: ""
}
</>
);
}
export default PestsGallery;
CodePudding user response:
Inconsistent types of imageToShow local state seems to be at fault (cannot test this without the actual repo). Typescript is great at catching this early.
imageToShow state has this type: { image: .jpeg, text: string }.
In imageCards callback on the img you pass { image: .jpeg } into showImage function, which then uses setImageToShow to set the image to show. Instead, you should be passing the correct state shape i.e. { image, text }.
Also, in your jsx, you need to access the image component in img tag like so:
<img alt="gallery" id="lightbox-img" src={imageToShow.image}></img>
If you look at your setImageToShow calls in showNext and showPrev, the nextImage variable is the entire image object e.g. { image: Bee, text: "Bee" }, since you access images_arr at a specific index (btw, keep you naming consistent to camelCase).
Code snippet aligned with above below for copy paste check:
import { useState } from 'react'
import Ant from '../../img/ant.jpeg'
import Bee from '../../img/bee.jpeg'
import Bedbug from '../../img/bedbug.jpeg'
import Wasp from '../../img/wasp.jpeg'
import Mouse from '../../img/mouse.jpeg'
// const images = [Bee, Ant, Bedbug, Wasp, Mouse];
const images_arr = [
{ image: Ant, text: 'Ant' },
{ image: Bee, text: 'Bee' },
{ image: Bedbug, text: 'Bedbug' },
{ image: Mouse, text: 'Mice' },
{ image: Wasp, text: 'Wasp' },
]
function PestsGallery() {
const [imageToShow, setImageToShow] = useState({})
const [lightboxDisplay, setLightBoxDisplay] = useState(false)
//looping through our images array to create img elements
const imageCards = images_arr.map(({ image, text }) => (
<>
<span>{text}</span>
<img
key={image}
alt={image}
className='image-card'
onClick={() => showImage({ image, text })}
src={image}
/>
</>
))
//function to show a specific image in the lightbox, amd make lightbox visible
const showImage = (image) => {
setImageToShow(image) // image is the object hence it will work
setLightBoxDisplay(true)
}
//hide lightbox
const hideLightBox = () => {
setLightBoxDisplay(false)
}
//show next image in lightbox - this is where the error is happening, when i clicke the arrow the next image is empty.
const showNext = (e) => {
e.stopPropagation()
let currentIndex = images_arr.indexOf(imageToShow)
if (currentIndex >= images_arr.length - 1) {
setLightBoxDisplay(false)
} else {
let nextImage = images_arr[currentIndex 1]
setImageToShow(nextImage)
}
}
const showPrev = (e) => {
e.stopPropagation()
let currentIndex = images_arr.indexOf(imageToShow)
if (currentIndex <= 0) {
setLightBoxDisplay(false)
} else {
let nextImage = images_arr[currentIndex - 1]
setImageToShow(nextImage)
}
}
return (
<>
<h2> Bugs we treat</h2>
<div>{imageCards}</div>
{lightboxDisplay ? (
<div id='lightbox' onClick={hideLightBox}>
<button onClick={showPrev}>⭠</button>
<img alt='gallery' id='lightbox-img' src={imageToShow.image}></img>
<button onClick={showNext}>⭢</button>
</div>
) : (
''
)}
</>
)
}
export default PestsGallery
