Модальные окна открываются все одновременно
Изучаю реакт и делаю страницу, на которой отображаются все картинки из файла json, при нажатии на каждую отдельную картинку должно открываться модальное окно с каждой конкретной картинкой. У меня открываются все вместе, перекрывая друг друга. Как можно исправить это?
Вот мой код:
import React, { useEffect, useState } from "react";
import axios from "axios";
import Card from "react-bootstrap/Card";
import Image from 'react-bootstrap/Image';
import Modal from 'react-bootstrap/Modal';
export default function Portfolio() {
const [state, setState] = useState({ persons: [] });
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
useEffect(() => {
axios.get("http://localhost:3000/portfolio-data.json").then((res) => {
const persons = res.data;
setState({ persons });
});
}, [setState]);
return (
<div className="container">
<div className="portfolio-wrapper">
{state.persons.map((person) => (
<>
<Card
style={{ width: "18rem" }}
className="portfolio-card"
onClick={handleShow}
>
<Card.Img variant="top" src={person.src} className="card-pic" />
<Card.Body>
<Card.Title>{person.title}</Card.Title>
<Card.Text>{person.desc}</Card.Text>
</Card.Body>
</Card>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>{person.title}</Modal.Title>
</Modal.Header>
<Modal.Body>
<Image src={person.src} fluid />
</Modal.Body>
</Modal>
</>
))}
</div>
</div>
);
}
Ответы (1 шт):
Автор решения: Избыток Сусликов
→ Ссылка
Потому что вы написали модальное окно внутри цикла map.
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>{person.title}</Modal.Title>
</Modal.Header>
<Modal.Body>
<Image src={person.src} fluid />
</Modal.Body>
</Modal>
Для решения просто напишите модальное окно за пределы цикла
{state.persons.map((person) => (
<>
<Card
style={{ width: "18rem" }}
className="portfolio-card"
onClick={handleShow}
>
<Card.Img variant="top" src={person.src} className="card-pic" />
<Card.Body>
<Card.Title>{person.title}</Card.Title>
<Card.Text>{person.desc}</Card.Text>
</Card.Body>
</Card>
</>
))}
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>{person.title}</Modal.Title>
</Modal.Header>
<Modal.Body>
<Image src={person.src} fluid />
</Modal.Body>
</Modal>
И не надо так писать отображения модального окна. Сохраняйте кликнутый элемент в стейте, чтобы показать его внутри модального окна за пределы цикла.
Правильно будет вот так:
export default function App() {
const [state, setState] = useState({ persons: [] });
const [show, setShow] = useState(false);
const [personState, setPersonState] = useState();
const handleShow = () => setShow(!show);
useEffect(() => {
axios.get("https://jsonplaceholder.typicode.com/users").then((res) => {
const persons = res.data;
setState({ persons });
});
}, [setState]);
return (
<div className="container">
<div className="portfolio-wrapper">
{state.persons.map((person) => (
<>
<Card
style={{ width: "18rem" }}
className="portfolio-card"
onClick={() => {
handleShow();
setPersonState(person);
}}
>
<Card.Body>
<Card.Title>{person.name}</Card.Title>
<Card.Text>{person.website}</Card.Text>
</Card.Body>
</Card>
</>
))}
<Modal show={show} onHide={() => setShow(false)}>
<Modal.Header closeButton>
<Modal.Title>{personState?.username}</Modal.Title>
</Modal.Header>
<Modal.Body>
<span>{personState?.email}</span>
</Modal.Body>
</Modal>
</div>
</div>
);
}