1

I'm still fairly new to React and I'm wondering how I go about ensuring that each card shows the correct data in the modal? Right now it is displaying all the modals at once and only displaying the last one.

I've added my updated code below but help on fixing this problem would be greatly appreciated!

// import projects into portfolio
import React, { useState } from 'react';

// react bootstrap imports
import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';


const projectData = [
    {
        id: 1,
        name: 'Project 1',
        photo: project1,
        url: 'https://',
        gitHub: 'https://',
        summary: 'Lorem ipsum',
        techSkills: 'abc'
    },
    {
        id: 2,
        name: 'Project 2',
        photo: project2,
        url: 'https://',
        gitHub: 'https://',
        summary: 'Lorem ipsum',
        techSkills: 'abc'
    },
    {
        id: 3,
        name: 'Project 3',
        url: 'https://',
        photo: project3,
        gitHub: 'https://',
        summary: 'Lorem ipsum',
        techSkills: 'abc'
    },
    {
        id: 4,
        name: 'Project 4',
        url: 'https://',
        photo: project4,
        gitHub: 'https://',
        summary: 'lorem ipsum',
        techSkills: 'abc'
    }
];

function Project(props) {


    // useState variables to display modals
    const [showModal, setShowModal] = useState(false);
    const handleClose = () => setShowModal(false);
    const handleShow = () => setShowModal(true);

    return (
        <div className='container'>
            <div className='row'>
                {projectData.map((data) => {
                    return (
                        <div className='col-3 d-flex mb-4' key={data.id}>
                            <Button onClick={handleShow} className="project-card card p-0 border-5 border-dark shadow-lg">
                                <img className='card-img shadow-lg' src={data.photo} alt={data.name} >
                                </img>
                            </Button>


                        </div>
                    );
                })}
                {projectData.map(({id, name, summary, techSkills, url, gitHub}) => {
                    return (
                        <Modal
                            {...props}
                            size="lg"
                            aria-labelledby="contained-modal-title-vcenter"
                            centered
                            show={showModal}
                            onHide={handleClose}
                            key={id}
                        >
                            <Modal.Header closeButton className="border-dark">
                                <Modal.Title className="" id="modal-title">
                                    {name}
                                </Modal.Title>
                            </Modal.Header>

                            <Modal.Body className="container">
                                <p>
                                    {summary}
                                </p>

                                <br />

                                <p>
                                    {techSkills}
                                </p>
                            </Modal.Body>
                            <Modal.Footer className="modal-bg border-dark">
                                <Button id="modal-button" className="" target='_blank' rel='noreferrer' href={url}>View live app here!</Button>
                                <Button id="modal-button" className="" target='_blank' rel='noreferrer' href={gitHub}>
                                    <span className='bi bi-github work-icon'></span>
                                </Button>
                            </Modal.Footer>
                        </Modal>
                    );
                })}
            </div>
        </div>
    );
}
Maggie
  • 11
  • 3
  • Are you abstracting parts of this code? It is difficult to answer without knowing what the data looks like or how you are passing it to other componnents. – zemaj Sep 08 '22 at 16:04
  • You create 1 modal for each item in data and then you open them all at once and close them all at once. e.g. if you have 5 items in data you will get 5 modals, but you only have 1 modalShow that will trigger all modals. – Disco Sep 08 '22 at 16:08
  • @zemaj I have abstracted some code that is in the objects as I didn't think it was needed. What info do you need to get a better picture of what is going on? – Maggie Sep 08 '22 at 16:53
  • @Disco So to trigger one modal at a time I need to have a modalShow for each modal? (that would be 7 in total) – Maggie Sep 08 '22 at 16:54
  • Yes, you could either change the `modalShow` to take an identifier like an ide to match instead if you want to keep the state in that top level. This is the correct way if you only want to show one at a time. Or you could move down the `modalShow` state where it is used e.g. make a new component that holds the card a button, this would allow you to open several modals at once. I think that you might also make more modals than you want, you should look over why you loop over `modalData`, could you pass down the info in a better way? – Disco Sep 09 '22 at 07:37
  • I updated my code so you can see the changes I made. I'm still having the same problem though :( @Disco – Maggie Sep 13 '22 at 21:21

1 Answers1

1

The state in your updated example is still a boolean which is either truth of false. If any button is pressed all modals will open. You can change this state to store a id instead. When button is pressed set id of that item, when modal is closed set state to undefined. See code below, with changes. The important changes are const handleShow = (id) => setShowModal(id); <Button onClick={()=>handleShow(data.id)} show={showModal === id}

// useState variables to display modals
const [showModal, setShowModal] = useState(undefined);
const handleClose = () => setShowModal(undefined);
const handleShow = (id) => setShowModal(id);

return (
    <div className='container'>
        <div className='row'>
            {projectData.map((data) => {
                return (
                    <div className='col-3 d-flex mb-4' key={data.id}>
                        <Button onClick={()=>handleShow(data.id)} className="project-card card p-0 border-5 border-dark shadow-lg">
                            <img className='card-img shadow-lg' src={data.photo} alt={data.name} >
                            </img>
                        </Button>


                    </div>
                );
            })}
            {projectData.map(({id, name, summary, techSkills, url, gitHub}) => {
                return (
                    <Modal
                        {...props}
                        size="lg"
                        aria-labelledby="contained-modal-title-vcenter"
                        centered
                        show={showModal === id}
                        onHide={handleClose}
                        key={id}
                    >
                        <Modal.Header closeButton className="border-dark">
                            <Modal.Title className="" id="modal-title">
                                {name}
                            </Modal.Title>
                        </Modal.Header>

                        <Modal.Body className="container">
                            <p>
                                {summary}
                            </p>

                            <br />

                            <p>
                                {techSkills}
                            </p>
                        </Modal.Body>
                        <Modal.Footer className="modal-bg border-dark">
                            <Button id="modal-button" className="" target='_blank' rel='noreferrer' href={url}>View live app here!</Button>
                            <Button id="modal-button" className="" target='_blank' rel='noreferrer' href={gitHub}>
                                <span className='bi bi-github work-icon'></span>
                            </Button>
                        </Modal.Footer>
                    </Modal>
                );
            })}
        </div>
    </div>
);
Disco
  • 1,304
  • 1
  • 6
  • 12