Reputation: 35
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;
Upvotes: 1
Views: 2605
Reputation: 1049
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
Upvotes: 0
Reputation: 67296
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.
Upvotes: 0