I'm currently trying to make an image gallery using react and bootstrap.
ignoring the actual content and syntax, this is kind of what the code looks like. I want a total of 6 images that are side by side in a 3x2 grid. Each image has a onHover where itll show a black transparent background with some text.
function Projects() {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const [show1, setShow1] = useState(false);
const handleClose1 = () => setShow1(false);
const handleShow1 = () => setShow1(true);
const [show1, setShow2] = useState(false);
const handleClose2 = () => setShow2(false);
const handleShow2 = () => setShow2(true);
x3 more times
return (
<div class="img__wrap"> // this is just the first image
<img class="projectCard" src={test} />
<div class="img__description_layer">
<p class="img__description">some text.</p>
<button onClick={handleShow}>test</button>
<Modal show={show} onHide={handleClose}>
<Modal.Header className="background" closeButton>
<Modal.Title className="smallerProjectHeadings">title</Modal.Title>
</Modal.Header>
<Modal.Body className="background">
<Image className='projectImg' src={image} alt='Oneshot' fluid />
</Modal.Body>
<Modal.Footer className="background" >
some stuff here
</Modal.Footer>
</Modal>
</div>
</div>
)
The issue is it looks kind of messy. I would have to repeat each of the useStates a total of 6 times to render 6 different modal popups. Is there a cleaner way to do this?
Something I was thinking I'd like to do is like this:
<button onClick={()=>{
<ModalPictures // this would a separate component
props='blah'
propsTwo='blah'
/>
}}
but when I try this, it doesn't actually do anything any advice would be appreciated.
Only one or maybe two useState
s are more than enough for what you're trying to do. And just because you have 6 images you don't need to use 6 modals.
I created a simple sandbox to show how this can be achieved. Click on any of the list items to see.
const arrayOfLength6 = Array(6)
.fill()
.map((_, i) => i);
const Modal = ({ show, data, onHide }) => {
if (!show) return null;
return (
<>
<p>{data}</p>
<button onClick={onHide}>Close</button>
</>
);
};
export default function App() {
const [selected, setSelected] = useState();
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<ul>
{arrayOfLength6.map((i) => (
<li onClick={() => setSelected(i)} key={i}>
I'm image at index {i}
</li>
))}
</ul>
<Modal
onHide={() => setSelected(undefined)}
show={typeof selected !== "undefined"}
data={selected}
/>
</div>
);
}
The idea is to keep track of the selected image in the state when it is clicked. In my example, I'm just storing the index of the image but you can store the data associated with an image when it's selected and pass the data as props to the modal.