I am building a React-App and I have a a problem with the use of components in my React-App. When i work with components like buttons or tables everything works, but when i use a modal there are problems. My serverside json looks like
let jsonlist = [
{
Title: "first title",
Listofitems: ["Item 01", "Item 02", "Item 03"]
},
{
Title: "second title",
Listofitems: ["Item 04", "Item 05", "Item 06"]
}
]
and I work with it on clientside like
import { React, useEffect, useState, useRef } from 'react';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
const ModalList = ({ socket }) => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
const [lists, setlist] = useState([]);
const fetchFact = () => {
fetch("http://myapi/getList")
.then((response) => response.json())
.then((data) => setlist(data));
}
useEffect(() => {
fetchFact()
}, []);
return (
<div className='container'>
{lists.map(singleobject => (
<div>
<div>{singleobject.title}</div>
<div>{singleobject.listofelement.join(', ')}</div>
<div>
<Button variant="primary" onClick={handleShow}>
{singleobject.title}
</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>{singleobject.title}</Modal.Title>
</Modal.Header>
<Modal.Body>{singleobject.listofelement.join(', ')}</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save
</Button>
</Modal.Footer>
</Modal></div>
</div>
))}
</div>
);
}
export default ModalList;
When i work with components like react-bootstrap/Accordion
or react-bootstrap/Table
evrything works fine and I can use/acess the right values for singleobject.title
and singleobject.listofelement
. The singleobject.title
inside the <Button>
gets the right value (the first button displays first title
and the second button displays second title
). But when I use singleobject.title
and singleobject.listofelement
in the Modal
both modals get as title
second title
and as singleobject.listofelement
both times ["Item 04", "Item 05", "Item 06"]
. Even if I increase the number of elements in the list, the values of the last object in the json are always used/displayed. What can I do that every element gets displayed just once like when i use react-bootstrap/Accordion
or react-bootstrap/Table
.
Thanks for your help
CodePudding user response:
Issue
All modal components use the same single show
state, so when you toggle any modal shown they all are shown and the last one rendered is highest in the DOM regarding view order.
Solution
Use a singleobject
id or some other unique property to specify showing a specific modal.
Example:
const jsonlist = [
{
id: '1', // <-- add id property
Title: "first title",
Listofitems: ["Item 01", "Item 02", "Item 03"],
},
{
id: '2',
Title: "second title",
Listofitems: ["Item 04", "Item 05", "Item 06"],
},
];
...
const ModalList = ({ socket }) => {
const [show, setShow] = useState(null);
const handleClose = () => setShow(null);
const handleShow = (id) => setShow(id);
...
return (
<div className='container'>
{lists.map(singleobject => (
<div>
<div>{singleobject.title}</div>
<div>{singleobject.listofelement.join(', ')}</div>
<div>
<Button
variant="primary"
onClick={() => handleShow(singleobject.id)} // <-- pass id
>
{singleobject.title}
</Button>
<Modal
show={show === singleobject.id} // <-- match id to show modal
onHide={handleClose}
>
....
</Modal>
</div>
</div>
))}
</div>
);
}