I am trying to a make Gallery application using React.JS and Reactstrap. I'm using the map()
function to display every piece of art in a Card. In every card, there is a button that opens a modal to show more data from the map function. My problem is when I'm clicking the button to open modal from any card it shows the data from the last card on the page.
The code:
const Artcards = ({ state, loading }, props) => {
const { buttonLabel, className } = props;
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal);
if (loading) {
return <h2>Loading</h2>;
}
return (
<CardGroup className="CardGroup">
{state.map((state, index) => {
return (
<div key={index}>
<Card className="Card" style={{ padding: "0", height: "39rem" }}>
<CardBody className="pt-3">
<CardTitle className="CardTitle">
Art Name:
<h6 className="CardParagraph">{state.artName}</h6>
</CardTitle>
<CardSubtitle>
Artist Name:
<h6 className="CardParagraph">{state.artistName}</h6>
</CardSubtitle>
<CardImg
top
src={state.source}
alt={state.artName}
/>
</CardBody>
<CardBody>
<CardText>
Description:
<div className="CardParagraph">{state.description}</div>
</CardText>
<CardText>
Price:<div className="CardParagraph">{state.price} </div>
</CardText>
<Button size="sm" color="danger" className=" m-1">
Buy
</Button>
<br></br>
<Button color="success" onClick={toggle}>
Contact Artist
</Button>
</CardBody>
<Modal
isOpen={modal}
state={state}
fade={false}
toggle={toggle}
className={className}
>
<ModalHeader className="bg-dark text-primary" toggle={toggle}>
here the {state.artistName} should be
</ModalHeader>
<ModalBody>
<p>Header:{state.artName}</p>
<textarea
style={{ overflow: "auto", resize: "none"}}
rows="5"
cols="60"
placeholder="Write your message"
></textarea>
<Input
type="text"
placeholder="Write Email or Tel number for response"
></Input>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={toggle}>
Send message
</Button>{" "}
<Button color="secondary" onClick={toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
</Card>
</div>
);
})}
</CardGroup>
);
};
I am trying to a make Gallery application using React.JS and Reactstrap. I'm using the map()
function to display every piece of art in a Card. In every card, there is a button that opens a modal to show more data from the map function. My problem is when I'm clicking the button to open modal from any card it shows the data from the last card on the page.
The code:
const Artcards = ({ state, loading }, props) => {
const { buttonLabel, className } = props;
const [modal, setModal] = useState(false);
const toggle = () => setModal(!modal);
if (loading) {
return <h2>Loading</h2>;
}
return (
<CardGroup className="CardGroup">
{state.map((state, index) => {
return (
<div key={index}>
<Card className="Card" style={{ padding: "0", height: "39rem" }}>
<CardBody className="pt-3">
<CardTitle className="CardTitle">
Art Name:
<h6 className="CardParagraph">{state.artName}</h6>
</CardTitle>
<CardSubtitle>
Artist Name:
<h6 className="CardParagraph">{state.artistName}</h6>
</CardSubtitle>
<CardImg
top
src={state.source}
alt={state.artName}
/>
</CardBody>
<CardBody>
<CardText>
Description:
<div className="CardParagraph">{state.description}</div>
</CardText>
<CardText>
Price:<div className="CardParagraph">{state.price} </div>
</CardText>
<Button size="sm" color="danger" className=" m-1">
Buy
</Button>
<br></br>
<Button color="success" onClick={toggle}>
Contact Artist
</Button>
</CardBody>
<Modal
isOpen={modal}
state={state}
fade={false}
toggle={toggle}
className={className}
>
<ModalHeader className="bg-dark text-primary" toggle={toggle}>
here the {state.artistName} should be
</ModalHeader>
<ModalBody>
<p>Header:{state.artName}</p>
<textarea
style={{ overflow: "auto", resize: "none"}}
rows="5"
cols="60"
placeholder="Write your message"
></textarea>
<Input
type="text"
placeholder="Write Email or Tel number for response"
></Input>
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={toggle}>
Send message
</Button>{" "}
<Button color="secondary" onClick={toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
</Card>
</div>
);
})}
</CardGroup>
);
};
Share
Improve this question
edited Dec 9, 2019 at 15:06
Afia
6835 silver badges17 bronze badges
asked Dec 9, 2019 at 14:36
Aviv CohenAviv Cohen
211 silver badge3 bronze badges
1
- You're creating a modal for each card. You don't need to do that. Create one (place it under the CardGroup, for example) and toggle that instead. – Andy Commented Dec 9, 2019 at 14:40
1 Answer
Reset to default 6What you are doing here isn't opening only the last, but you are opening all modals and only the last is showing because is on top of all others.
What you need to do is have only one modal and save the index of the clicked card and then only display the data from that card.
So here is what you need to do
- Remove the modal from inside the
.map
- Have another state to store the index or the data from the card
- Only display in the modal the data from the selected card
You also have some kind of weird use of the variable state
in alot of places where you have state
ming from props and then using the same name inside .map
. You should change that name to something more descriptive, because this makes things very confusing.