I started learning React
recently. I made a page with Images. When I click on the images it opens a Modal, and my plan is to display the related image in the Modal.
So basically my idea is to data-bind the image to the Modal.
The question is: How could I bind the images to the Modal function?
The modal: Modal.jsx
const Modal = ({ setIsOpen }) => {
return (
<>
<div onClick={() => setIsOpen(false)} className={styles.ewn__darkBG}/>
<div className={styles.ewn__centered}>
<div className={styles.ewn__modal}>
<div className={styles.ewn__modalHeader}>
<h5 className={styles.ewn__heading}>Dialog</h5>
</div>
<button className={styles.ewn__closeBtn} onClick={() => setIsOpen(false)}>
<RiCloseLine style={{ marginBottom: "-3px" }} />
</button>
<div className={styles.ewn__modalContent}>
I would like to display image here available in the Vocabulary.js
</div>
<div className={styles.ewn__modalActions}>
<div className={styles.ewn__actionsContainer}>
<button
className={styles.ewn__cancelBtn}
onClick={() => setIsOpen(false)}
>
Cancel
</button>
</div>
</div>
</div>
</div>
</>
);
};
export default Modal;
The page: Vocabulary.js
Explanation: I imported image files, put them in an array and display them with mapping.
const IMAGES = [
{img: Vocab1 }, {img: Vocab2 } , {img: Vocab3 } , {img: Vocab4 }, {img: Vocab5 },
{img: Vocab6 }, {img: Vocab7 }, {img: Vocab8 }, {img: Vocab9 }, {img: Vocab10 },
{img: Vocab11 }, {img: Vocab12 }, {img: Vocab13 }, {img: Vocab14 }, {img: Vocab15 },
{img: Vocab16 }, {img: Vocab17 }, {img: Vocab18 }, {img: Vocab19 }, {img: Vocab20 },
{img: Vocab21 }, {img: Vocab22 }, {img: Vocab23 }, {img: Vocab24 }
];
const Vocabulary = () =>{
const [isOpen, setIsOpen] = useState(false);
return <>
<div >
{IMAGES.map(IMAGES=> {
return (
<>
<div className="card vocabulary--card mt-5 mb-5 me-5 ms-5">
<img src={IMAGES.img} alt="Vocab1" className="card-img-top" onClick={() => setIsOpen(true)}/>
<div className="card-body">
{isOpen && <Modal setIsOpen={setIsOpen} />}
</div>
</div>
</>
)
})}
</div>
</>
}
The modal at the moment: Modal.jsx
P.S.: I don't use bootstrap because for some reason it displays only the first image everywhere, and the second reason is that I would like to practise React.
CodePudding user response:
const Vocabulary = () => {
const [isOpen, setIsOpen] = useState(null);
return (
<>
<div >
{IMAGES.map((imageData) => {
return (
<>
<div className="card vocabulary--card mt-5 mb-5 me-5 ms-5">
<img
src={imageData.img}
alt="Vocab1"
className="card-img-top"
{/* send the clicked image data to the state */}
onClick={() => setIsOpen(imageData)}
/>
<div className="card-body">
<p
className="card-text dropdown-toggle"
type="button"
id="dropdownMenuButton1"
data-bs-toggle="dropdown"
aria-expanded="false"
></p>
{Boolean(isOpen) && (
{/* bind the selected image data state to a data prop on Modal */}
<Modal setIsOpen={setIsOpen} data={isOpen} />
)}
</div>
</div>
</>
);
})}
</div>
</>
);
};
You could set the clicked item in the state instead of a boolean. This way you could share the selected image data to the modal by adding a prop to the Modal which accepts this data.
CodePudding user response:
Vocabulary.js
const Vocabulary = ( ) => {
const [isOpen, setIsOpen] = useState(null);
return (
<>
<div >
{IMAGES.map((imageData) => {
return (
<>
<div className="card vocabulary__card mt-5 mb-5 me-5 ms-5">
<img
src={imageData.img}
alt="Vocab1"
className="card-img-top vocabulary--img"
// {/* send the clicked image data to the state */}
onClick={() => setIsOpen(imageData)}
/>
<div className="card-body">
{Boolean(isOpen) && (
// bind the selected image data state to a data prop on Modal
<Modal
data={isOpen} image={isOpen.img}
// close the modal
setIsOpen={setIsOpen}
/>
)}
</div>
</div>
</>
);
})}
</div>
</>
);
};
Modal.jsx
const Modal = ({ image, setIsOpen }) => {
return (
<>
<div onClick={() => setIsOpen(false)} className={styles.ewn__darkBG}/>
<div className={styles.ewn__centered}>
<div className={styles.ewn__modal}>
<div className={styles.ewn__modalHeader}>
</div>
<button className={styles.ewn__closeBtn} onClick={() => setIsOpen(false)}>
<RiCloseLine style={{ marginBottom: "-3px" }} />
</button>
<div className={styles.ewn__modalContent}>
<img className={styles.ewn_modal_img} src={image} alt="modal" />
</div>
<div className={styles.ewn__modalActions}>
<div className={styles.ewn__actionsContainer}>
</div>
</div>
</div>
</div>
</>
);
};
export default Modal;