Home > Software engineering >  Problem getting the right values using component react-bootstrap/Modal
Problem getting the right values using component react-bootstrap/Modal

Time:11-04

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>
  );
}
  • Related