1

im trying to make a subpage for a record label, i need to display all the artists on cards and then have their full profile displayed on a modal, whenever i try to open the modal all of them open and close when i click the card button, i've tried creating a constructor(props) with state component but wasnt able to make the state recieve the key id of the artist . i've been trying for weeks trying to adapt other examples to my own code with no results, Thank you so much for your time!

import React, {useState, setShow, Component} from 'react';
import {CardDeck, Navbar, NavLink, Col, Row, Image, Container, Card, CardImg, CardBody, CardText } from 'react-bootstrap';
import Button from 'react-bootstrap/Button'; 
import Modal from 'react-bootstrap/Modal';

const Artistas = [ {id:1,
img:require("../assets/images/artists-01.jpg"), 
title: 'Artist 1', 
content: 'Lorem Ipsum',
    musica:"https://open.spotify.com/embed/artist/1wA3nwZy9EriceVVQlEmEx",
    genres:["Punk ", "Rock"]},
  
    {id: 2, 
img:require("../assets/images/artists-04.jpg"), 
title: "Artist 2", 
content: 'lorem ipsum',
    musica:"https://open.spotify.com/embed/artist/1wA3nwZy9EriceVVQlEmEx"},
   ];


function ArtistsPage() {
  
    
const [show, setShow] = useState(false);
  const handleClose = () => setShow(false);
  const handleShow = () => setShow(true);

const Artistxs = Artistas.map(artist => 
<div>
<Card key={artist.id}>
  <Card.Img variant="top" src={artist.img} />
  <Card.Body>
  <Button onClick={handleShow}>{artist.title}</Button>
 <Card.Text>
  </Card.Text> 
  </Card.Body>
</Card>
<>
<Modal
        show={show}
        onHide={handleClose}
        backdrop="static"
        keyboard={false}
        centered
        size="lg"
      >
        <Modal.Header closeButton>
          <Modal.Title>{artist.title}</Modal.Title>
        </Modal.Header>
        <Modal.Body className="row">
        <div class="col-md-8">
        <Image src={artist.img} />
  </div>
  <div class="col-md-4">
    <p>{artist.content}</p>
  </div>
        </Modal.Body>
        <Modal.Footer>
          <Button onClick={handleClose} >
            Close
          </Button>
        </Modal.Footer>
      </Modal>
</>
</div>
 )


  return(
    <div>
      <Container className="container">
<Row className="row">
  <Col className="">{Artistxs}
</Col>
</Row>
</Container>
</div>
  );

}



export default ArtistsPage; 
Octavio Kh
  • 35
  • 1
  • 6
  • Why r u creating instances of Model with map? – Guruling Kumbhar Jan 21 '21 at 20:53
  • Creating separate component for a Model and passing id or a index as a props to it on button click to it should work. According to id or index then u can show the data in a model. – Guruling Kumbhar Jan 21 '21 at 20:59
  • hi @GurulingKumbhar because i haven't been able to make it render outside the map function.... do you have an example? i just moved the Modal below the map inside the ArtistPage, but still cant make it to work, thank you so much for your time – Octavio Kh Jan 21 '21 at 23:14
  • ok, let me create one basic example for u in answers. May help u to resolve. – Guruling Kumbhar Jan 22 '21 at 10:17
  • @GurulingKumbhar thank u so much for your help ! :) the StackOverflow community is amazing! – Octavio Kh Jan 24 '21 at 17:10

2 Answers2

0

You only need 1 Modal. So you can move Modal out of your map.

Then, you need to figure out how to indicate which artist to show in the Modal.

One way to do that is to pass the artist.id:

<Button onClick={handleShow(artist.id)}>{artist.title}</Button>

But now handleShow needs to return a function:

const handleShow = (artistId) => () => setShow(artistId);

I've also changes show to be which artist id instead of a boolean. (This assumes artist ids will not be zero, at the moment)

Once in the Modal, you need to find the selected artist:

Artistxs.find(artist => artist.id === artistId);

This should get you going.

Davin Tryon
  • 66,517
  • 15
  • 143
  • 132
  • thank u so much for your quick response, i moved the Modal down the map, i added the onClick to the button i did a ```function Modalx(){ Artistxs.find(artist => artist.id === artistId); return () render () //also changed const [artistId, setShow] = useState(artistId); const handleClose = () => setShow(false); const handleShow = (artistId) => () => setShow(artistId); // and called the function in a return( {Artistxs}{Modalx} )``` but still i cant make it work, thank u so much <3 – Octavio Kh Jan 21 '21 at 23:09
0

You can create separate component for Modal and pass the object through Props to display relevant info and handle modal events.

In example below, not toggling the actual modal but u can use the props to toggle it.

function ArtistAddtionalInfo(props) {
  return (
  // Modal can be here with details in artistInfo and other props 
  <div className="modal_dummy"> 
    Below Props can be used to handle actual model popup 
    <h1> Hello, { props.artistInfo.title }</h1>
    <div>{ props.artistInfo.id }</div>
    <div>{ props.artistInfo.img }</div>
    <div>{ props.artistInfo.content }</div>
    <div>showModel: {props.showModel ? 'true' : 'false'}</div>
    <button onClick = {() => props.handleModalClose()} > close </button>
  </div>
  
  )
}

class TodoApp extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
        items: [ {id:1,
img:"../assets/images/artists-01.jpg", 
title: 'Artist 1', 
content: 'Lorem Ipsum',
    musica:"https://open.spotify.com/embed/artist/1wA3nwZy9EriceVVQlEmEx",
    genres:["Punk ", "Rock"]},
  
    {id: 2, 
img:"../assets/images/artists-04.jpg", 
title: "Artist 2", 
content: 'lorem ipsum',
    musica:"https://open.spotify.com/embed/artist/1wA3nwZy9EriceVVQlEmEx"},
   ],
   artistInfo:  {},
   isShowModel: false
    }
  }
  
handleShow = (artist) =>{
     this.setState({
         artistInfo:artist,
       isShowModel: true
     });
  }
  
handleOnhide = () =>{
     this.setState({
         isShowModel: false
     });
}

render() {
    return (
      <div className="container">
        <div className="row">
            <div className="">
                { 
                this.state.items.map(artist => 
                   <div className="card" key={artist.id}>
                    <img className="card_image" src={artist.img} />
                    <div className="card_body">
                        <button onClick={ () => { this.handleShow(artist)}}> {artist.title} </button>
                        <div className="card_text">
                        </div> 
                    </div>
                  </div>
             )
            } 
          </div>
        </div>
        {
        this.state.isShowModel &&
        <ArtistAddtionalInfo 
          artistInfo = { this.state.artistInfo }
          showModel = {this.state.isShowModel}
          handleModalClose = {() => {this.handleOnhide()}}
        />
        }
      </div>
    )
  }
}

ReactDOM.render(<TodoApp />, document.querySelector("#app"))

JSFiddle see it in action

Guruling Kumbhar
  • 1,039
  • 1
  • 8
  • 18