Pandounours
Pandounours

Reputation: 21

How to make a dynamic modal in React?

I would like to open a modal when I click on a card, and this modal contains more informations about the card content that was clicked.

Here in my example, the cards are replaced by buttons.

So here how to change the modal content depending on the button clicked ?

I saw this post : Change react-modal data dynamically. But I don't understand his solution.

App.js :

function App() {
    const [modal, setModal] = useState({ show: false, data: null });

    const openNoWebsite = () => {
        setModal({ show: true, data: { title: 'No website in sight', subtitle: 'Having a website in 2021 is essential.' } });
    };

    const openMoreMoney = () => {
        setModal({ show: true, data: { title: 'More money', subtitle: "You think you have an awesome product, but people don't really notice it and your sales numbers are not going up."} });

    const handleCloseModal = () => {
        setModal({ show: false, data: null });
    };
   return {
   <div className="main">
      <button className="solidText" onClick={openNoWebsite}>
      Button 1
      </button>
    <button className="solidText" onClick={openMoreMoney}>
      Button 2
      </button>
      {modal.show && modal.data && <Modal closeModal={handleCloseModal} />}

   </div>
   }
}

Modal.jsx :

function Modal({ closeModal, data }) {
    return (
        <div className="modal-container">
            <div className="modal">
                <button className="btn btn--close" onClick={() => closeModal()}>X</button>
                <div className="modal__body">
                    <h1 className="modal__title">{data.title}</h1>
                    <h2 className="modal__subtitle">{data.subtitle}</h2>
                    <ul>
                        <span>How I will help you :</span>
                        <li>Discover together your goals through a strategy session</li>
                        <li>Discuss about the possible solutions to implement</li>
                        <li>A glorious online presence a.k.a. website</li>
                    </ul>
                </div>
                <div className="modal__footer">
                    <p>Wanna put your business out there ?</p>
                    <button className="btn btn--main">LET'S TALK</button>
                </div>
            </div>
        </div>
    )
}

Upvotes: 2

Views: 6919

Answers (2)

Nicolas Menettrier
Nicolas Menettrier

Reputation: 1679

What you can do is to use a state that contain the data you want to show inside your Modal, usually what I do is that I create a state const [modal, setModal] = useState({ show:false, data: null }) and when I press a button I update data accordingly to what I want to show.

Here I used car caracteristic put you can put whatever you want (description, big text, etc...).

The state show is not really usefull but I prefer to use it for clarity (you can just check if !data to know if you want to open or not your modal)

Example

function Modal({ closeModal, data }) {
  return (
    <div className="modal-container">
      <div className="modal">
        <button className="btn btn--close" onClick={() => closeModal()}>
          X
        </button>
        <div className="modal__body">
          <h1 className="modal__title">
            {data.name} {data.color}
          </h1>
          <h2 className="modal__subtitle">Having a website in 2021 is essential.</h2>
          <ul>
            <span>How I will help you :</span>
            <li>Discover together your goals through a strategy session</li>
            <li>Discuss about the possible solutions to implement</li>
            <li>A glorious online presence a.k.a. website</li>
          </ul>
        </div>
        <div className="modal__footer">
          <p>Wanna put your business out there ?</p>
          <button className="btn btn--main">{data.name}</button>
        </div>
      </div>
    </div>
  );
}

function App() {
  const [modal, setModal] = useState({ show: false, data: null });

  const openAudi = () => {
    setModal({ show: true, data: { name: 'Audi', color: 'red' } });
  };

  const openBMW = () => {
    setModal({ show: true, data: { name: 'BMW', color: 'blue' } });
  };

  const handleClose = () => {
    setModal({ show: false, data: null });
  };

  return (
    <div className="main">
      <button className="solidText" onClick={openAudi}>
        Button Audi
      </button>
      <button className="solidText" onClick={openBMW}>
        Button BMW
      </button>
      {modal.show && modal.data && <Modal closeModal={handleClose} data={modal.data} />}
    </div>
  );
}

Upvotes: 4

Pandounours
Pandounours

Reputation: 21

I found this solution, not sure if it's the best but it work.

const [modal, setModal] = useState({ show: false, requestedModalId: 0});

const handleOpenModal = (id) => {
    setModal({ show: true, requestedModalId: id });
};

const handleCloseModal = () => {
    setModal({ show: false });
};

return {
    <div className="main">
        <button onClick={() => handleOpenModal(1)}>Button 1</button>
        <button onClick={() => handleOpenModal(2)}>Button 2</button>
        {modal.show && modal.requestedModalId === 1 && <Modal closeModal={handleCloseModal}>
           <div>Modal Child 1</div>
        </Modal>}
        {modal.show && modal.requestedModalId === 2 && <Modal closeModal={handleCloseModal}>
           <div>Modal Child 2</div>
        </Modal>}
    </div>
}
function Modal(props) {
    return (
        <div className="modal-container">
            <div className="modal">
                <button className="btn btn--close" onClick={() => props.closeModal()}>X</button>
                {props.children}
            </div>
        </div>
    )
}

Upvotes: 0

Related Questions