Search code examples
reactjsdictionarymodal-dialogreact-modal

How do I use React Modal with a map function?


I'm mapping through data, I want to click on an image and have a modal popup with the data.title and data.info. Each modal is only showing the last data from my array. I've read that all the modals are popping up together and I'm only seeing the last one but I don't quite understand how to solve the problem, particularly with function components in React. TIA


 export default function SomeComponent   
 const [modalIsOpen, setModalIsOpen] = 
 useState(false);
 const customStyles = {
  content: {
    top: '35%',
    left: '50%',
    right: 'auto',
    bottom: 'auto',
    marginRight: '-50%',
    width: '60%',
    transform: 'translate(-40%, -10%)',
  },
}
  return (
    <div className="container">


    { somedata.map((data) => 
    (<div className='item' key={data.id} >
    <img src={data.img} alt='' onClick={()=> setModalIsOpen(true)} />
    <Modal isOpen={modalIsOpen} onRequestClose={() => setModalIsOpen(false)} style={customStyles}>
      <h1>{data.title</h1>
      <p>{data.content</p> 
    <div>
    <button onClick={() => setModalIsOpen(false)}>X</button>
    </div>
    </Modal>
   </div>))}
 </div>
</div>
  );}

Solution

  • You should use only one instance of Modal component and pass on the data of the clicked image to it using a state. Each time you click on an image, the data for modal should be updated with the data of the clicked image. See the example below. I've modified your code to make it work.

     export default function SomeComponent() {  
       const [modalIsOpen, setModalIsOpen] = useState(false);
       const [modalData, setModalData] = useState(null);
       const customStyles = {
        content: {
          top: '35%',
          left: '50%',
          right: 'auto',
          bottom: 'auto',
          marginRight: '-50%',
          width: '60%',
          transform: 'translate(-40%, -10%)',
        },
      }
      return (
        <>
          <div className="container">
            {somedata.map(data => (
              <div className='item' key={data.id} >
                <img 
                  src={data.img} 
                  alt='' 
                  onClick={()=> {
                    setModalData(data);
                    setModalIsOpen(true);
                  }
                />
              </div>
            ))}
          </div>
          <Modal isOpen={modalIsOpen} onRequestClose={() => setModalIsOpen(false)} style={customStyles}>
            <h1>{modalData.title}</h1>
            <p>{modalData.content}</p> 
            <div>
             <button onClick={() => setModalIsOpen(false)}>X</button>
            </div>
          </Modal>
        </>
      )
    }