Just open the clicked modal?

Asked

Viewed 63 times

0

I have a map of a array object.

<S.Section>
    {data.slice(oldItems, showItems).map((it, index) => {
      return (
        <>
          <S.Box key={index} onClick={openDetails}>
            <S.Image src={it.picture.large} />
            <S.Gender>{it.gender === "male" ? "Masculino" : "Feminino"}</S.Gender>
            <S.Name>
              {it.name.title} {it.name.first} {it.name.last}
            </S.Name>
            <S.Email>{it.email}</S.Email>
          </S.Box>
          {openInfo && (
            <Details data={it} toggleModal={openDetails} />
          )}
        </>
      );
    })}
</S.Section>

I wanted to: when clicking on a Box, it opened only the modal with the information of the Box clicked. The problem: All Boxes that are in the map current, when clicking on any one are being opened. I believe the problem lies in the referencing of data={it} for the it has all the objects of map and I can’t tell them apart, because I don’t have an ID coming from api.

One of the objects coming from api (dice fake)

{
    "gender":"female",
    "name":{
        "title":"mrs",
        "first":"ione",
        "last":"da costa"
    },
    "location": {
      "street":"8614 avenida vinícius de morais",
      "city":"ponta grossa",
      "state":"rondônia",
      "postcode":97701,
      "coordinates":{
        "latitude":"-76.3253",
        "longitude":"137.9437"
      },
      "timezone":{
        "offset":"-1:00",
        "description":"Azores, Cape Verde Islands"
      }
    },
    "email":"[email protected]",
    "dob":{
      "date":"1968-01-24T18:03:23Z",
      "age":50
    },
    "registered":{
      "date":"2004-01-23T23:54:33Z",
      "age":14
    },
    "phone":"(01) 5415-5648",
    "cell":"(10) 8264-5550",
    "picture":{
      "large":"https://randomuser.me/api/portraits/women/46.jpg",
      "medium":"https://randomuser.me/api/portraits/med/women/46.jpg",
      "thumbnail":"https://randomuser.me/api/portraits/thumb/women/46.jpg"
    }
}
  • How are the objects coming from the API? Post them too.

  • I edited the question with the object

  • Even if the API does not specifically have an ID you can see some information that it does not repeat and use as the key parameter in the map. In this case above I think it could be the email, but I believe that this API has a field called uuid that would look great to use, only in the case Voce has to make your application return this field in fetch

  • How is the method openDetails?

  • Is: const [openInfo, setOpenInfo] = useState(false); const openDetails = () => { setOpenInfo(!openInfo); }

  • Important you [Dit] your question and explain objectively and punctually the difficulty found, accompanied by a [mcve] of the problem and attempt to solve. To better enjoy the site, understand and avoid closures and negativities worth reading the Stack Overflow Survival Guide in English.

Show 1 more comment

1 answer

1


Was used in this example the React Bootstrap to display Modal, so what I do has a variable to control when the modal will be displayed (variable show) and I also have another variable to load the individual information of the selected and clicked item, not needing to know which is the item in a query, its value is already forced inside a function with parameter.

It all starts with the component <App /> and when loading the other component I pass the variables and functions so that the other components share the same information.

Minimal example:

function Modal({show, card, handleClose}) {
  var Modal = ReactBootstrap.Modal;
  var Button = ReactBootstrap.Button;
  return (
    <div>
      <Modal show={show}>
        <Modal.Header>
          {card && card.name.title}
          {' '}
          {card && card.name.first}
          {' '}
          {card && card.name.last}
        </Modal.Header>
        <Modal.Body>
          <div>{card && card.email}</div>
          <div>{card && card.location.street}</div>
        </Modal.Body>
        <Modal.Footer>
          <Button variant="secondary" onClick={handleClose}>
                            Fechar
          </Button>                 
        </Modal.Footer>
      </Modal>
    </div> 
  )
}

function Card({card, handleOpenCard}) {
  return (
    <div class="card" style={{width: '18rem', margin: 10}}>
      <div class="card-body">
        <h5 class="card-title">{card.name.first}</h5>
        <h6 class="card-subtitle mb-2 text-muted">
        {card.email}
        </h6>
        <p class="card-text">a</p>
        <button class="btn btn-link" onClick={handleOpenCard}>
        Abrir
        </button>          
      </div>
    </div>
  )
}
function App() {
  const [items, setItems] = React.useState(data);
  const [card, setCard] = React.useState(null);
  const [show, setShow] = React.useState(false);
  const handleOpenCard = (card) => {      
    setCard(card);
    setShow(true);    
  }
  const handleClose = (e) => {    
    setShow(false);
    setCard(null);
  }
  return (
    <div>
    <Modal card={card} show={show} handleClose={handleClose} />
    {items.map((card, idx) => 
      (<Card idx={idx} 
        card={card} 
        handleOpenCard={e => handleOpenCard(card)}
       />
    ))}
    </div>
  )
}


const data = [{
  "gender": "male",
  "name": {
    "title": "mr",
    "first": "souza",
    "last": "da costa"
  },
  "location": {
    "street": "8614 avenida vinícius de morais",
    "city": "ponta grossa",
    "state": "rondônia",
    "postcode": 97701,
    "coordinates": {
      "latitude": "-76.3253",
      "longitude": "137.9437"
    },
    "timezone": {
      "offset": "-1:00",
      "description": "Azores, Cape Verde Islands"
    }
  },
  "email": "[email protected]",
  "dob": {
    "date": "1968-01-24T18:03:23Z",
    "age": 50
  },
  "registered": {
    "date": "2004-01-23T23:54:33Z",
    "age": 14
  },
  "phone": "(01) 5415-5648",
  "cell": "(10) 8264-5550",
  "picture": {
    "large": "https://randomuser.me/api/portraits/women/46.jpg",
    "medium": "https://randomuser.me/api/portraits/med/women/46.jpg",
    "thumbnail": "https://randomuser.me/api/portraits/thumb/women/46.jpg"
  }
}, {
  "gender": "female",
  "name": {
    "title": "mrs",
    "first": "ione",
    "last": "da costa"
  },
  "location": {
    "street": "8614 avenida vinícius de morais",
    "city": "ponta grossa",
    "state": "rondônia",
    "postcode": 97701,
    "coordinates": {
      "latitude": "-76.3253",
      "longitude": "137.9437"
    },
    "timezone": {
      "offset": "-1:00",
      "description": "Azores, Cape Verde Islands"
    }
  },
  "email": "[email protected]",
  "dob": {
    "date": "1968-01-24T18:03:23Z",
    "age": 50
  },
  "registered": {
    "date": "2004-01-23T23:54:33Z",
    "age": 14
  },
  "phone": "(01) 5415-5648",
  "cell": "(10) 8264-5550",
  "picture": {
    "large": "https://randomuser.me/api/portraits/women/46.jpg",
    "medium": "https://randomuser.me/api/portraits/med/women/46.jpg",
    "thumbnail": "https://randomuser.me/api/portraits/thumb/women/46.jpg"
  }
}];
ReactDOM.render( <App/> , document.getElementById('root'));
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous" />
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<script
  src="https://unpkg.com/react-bootstrap@next/dist/react-bootstrap.min.js"
  crossorigin></script>

<div id="root"></div>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.