我有此代码:
const useStyles = makeStyles({
card: {
maxWidth: 345,
},
media: {
height: 140,
},
});
export default function AlbumCard(props) {
const classes = useStyles();
let artist
let albumName
let artistHead
albumName = props.album.name
artist = props.album.artists.map((name, key) => {
if(albumName != name.name) {
return <Typography variant="body2" color="textSecondary" component="p" key={key}>
{name.name}
</Typography>
}
})
artistHead = props.album.artists.length > 1 ? 'Artists:' : 'Artist:'
const album = props.album
const page = "https://open.spotify.com/album/" + album.id
return(
<Grid item md={3}>
<Card className={classes.card}>
<CardActionArea>
<CardMedia
className={classes.card}
component="img"
alt={album.name}
height="140"
width="100"
image={album.images[0].url}
title={album.name}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{album.name}
</Typography>
<Typography variant="body2" color="textSecondary" component="h3">
Release Date
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
{album.release_date}
</Typography>
<Typography variant="body2" color="textSecondary" component="h3">
{artistHead}
</Typography>
{artist}
<Typography variant="body2" color="textSecondary" component="p">
{!props.showMarkets && album.available_markets.map((c, i) => {
return <li key={i}>{c}</li>
})}
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
<a href={page} target="_blank">Album Page</a>
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
<a href={album.uri}>Open In App</a>
</Typography>
</CardContent>
</CardActionArea>
<Button
size="small"
color="primary"
onClick={props.handleShow}
>{!props.showMarkets ? "Hide Markets" : "Show Markets"}</Button>
</Card>
</Grid>
)
}
此代码由以下高级组件呈现:
class Album extends React.Component {
constructor(props) {
super(props)
this.state={
artistId: '',
albumName: '',
holeData: '',
marketsDisplay: true,
data: []
}
this.handleOnChange = this.handleOnChange.bind(this)
this.handleOnClick = this.handleOnClick.bind(this)
}
handleOnChange(e) {
e.preventDefault()
const target = e.target
const value = target.value
const name = target.name
this.setState({
[name]: value
})
}
handleAlert(e) {
e.preventDefault()
alert('Plead type the album name and/or artist id')
}
handleOnClick(e) {
e.preventDefault()
fetch('https://api.spotify.com/v1/artists/' + this.state.artistId + '/albums', {
"method": "GET",
"dataType": "json",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer " + this.props.access_token
}
})
.then(res => res.json())
.then((data) => {
this.setState({
holeData: data,
data: data.items
})
})
}
ToggleButton() {
this.setState((currentState) => ({
marketsDisplay: !currentState.marketsDisplay
}))
}
render() {
let albums
let albumList
let display
albumList = this.state.data.map((name, key) => {
return <AlbumCard
album={name}
showMarkets={this.state.marketsDisplay}
handleShow={() => this.ToggleButton()}
key={key}
/>
})
return(
<React.Fragment>
<CssBaseline />
<Container maxWidth="sm">
<Typography component="div" style={{backgroundColor: '#cfe8fc', marginTop: '5%', marginBottom: '5%'}}>
<FormControl fullWidth={true}>
<TextField
id="outlined-basic"
label="Artist ID"
variant="outlined"
type="text"
name="artistId"
value={this.state.artistId}
onChange={this.handleOnChange}>
</TextField>
<Button
type="button"
color="secondary"
onClick={this.state.artistId ? this.handleOnClick : this.handleAlert}>Getir</Button>
</FormControl>
</Typography>
</Container>
<Grid container spacing={6}>
{albumList}
</Grid>
</React.Fragment>
)
}
}
export default Album
最后我有多张卡片。当我单击任何卡的按钮时,我希望打开一张 JUST 卡的列表,但是发生的情况是当我单击任意按钮时,所有卡的列表都在打开。 我无法解决这个问题。 我被卡住了。 请帮我。 谢谢。
答案 0 :(得分:0)
好吧,我做到了。
我通过从Spotify API返回数据来创建状态,并将值设置为false。 之后,我创建了两个函数。一种是使值为true,另一种为false。 最后,我将功能提供给AlbumCard组件的props作为值。
这是我的代码的最新版本(也有与此问题无关的其他更改):
Album.js
import React from 'react';
import CssBaseline from '@material-ui/core/CssBaseline';
import Typography from '@material-ui/core/Typography';
import Container from '@material-ui/core/Container';
import FormControl from '@material-ui/core/FormControl';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
import AlbumCard from './Card';
import Grid from '@material-ui/core/Grid';
import SelectArtist from './SelectArtist'
class Album extends React.Component {
constructor(props) {
super(props)
this.state={
artistId: '',
artistName: '',
holeData: '',
artists: '',
showSelect: false,
marketsDisplay: true,
data: []
}
this.handleOnChange = this.handleOnChange.bind(this)
this.handleOnClick = this.handleOnClick.bind(this)
this.handleOnArtists = this.handleOnArtists.bind(this)
}
handleOnChange(e) {
e.preventDefault()
const target = e.target
const value = target.value
const name = target.name
this.setState({
[name]: value
})
}
handleAlert(e) {
e.preventDefault()
alert('Plead type the album name and/or artist id')
}
handleOnClick(e) {
e.preventDefault()
fetch('https://api.spotify.com/v1/artists/' + this.state.artistId + '/albums', {
"method": "GET",
"dataType": "json",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer " + this.props.access_token
}
})
.then(res => res.json())
.then((data) => {
let idObj={}
this.setState({
holeData: data,
data: data.items,
})
//create states with false value
//from returning data
data.items.map((name, key) => {
this.setState({
[name.id]: false
})
})
})
}
handleOnArtists(e) {
e.preventDefault()
fetch('https://api.spotify.com/v1/search?q=' + encodeURIComponent(this.state.artistName) + '&type=artist', {
"method": "GET",
"dataType": "json",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer " + this.props.access_token
}
})
.then(res => res.json())
.then((data) => {
this.setState({
artists: data.artists.items,
showSelect: true
})
})
}
//make the value true
ToggleOpen(event, type) {
this.setState({
[type]: true
})
}
//make the value false
ToggleClose(event, type) {
this.setState({
[type]: false
})
}
render() {
let albumList
let artists
let albumId
artists = <SelectArtist
artists={this.state.artists}
name="artistId"
artistId={this.state.artistId}
handleOnChange={this.handleOnChange}
showSelect={this.state.showSelect}
/>
albumList = this.state.data.map((name, key) => {
return <AlbumCard
album={name}
//give the states to AlbumCard component as props
showMarkets={this.state[name.id]}
//give the functions to AlbumCard component as props
handleShow={
this.state[name.id] ?
event => this.ToggleClose(event, name.id) :
event => this.ToggleOpen(event, name.id)
}
key={key}
/>
})
return(
<React.Fragment>
<CssBaseline />
<Container>
<Typography component="div" style={{marginTop: '5%', marginBottom: '5%'}}>
<FormControl fullWidth={true}>
<TextField
id="outlined-basic"
label="Artist Name"
variant="outlined"
type="text"
name="artistName"
value={this.state.artistName}
onChange={this.handleOnChange}>
</TextField>
<Button
variant="contained"
type="button"
color="primary"
onClick={this.state.artistName ? this.handleOnArtists : this.handleAlert}>Get Artists</Button>
{this.state.showSelect ? artists : null}
{
this.state.artistId ?
<Button
variant="contained"
type="button"
color="primary"
onClick={this.state.artistId ? this.handleOnClick : this.handleAlert}>
Get Albums
</Button> : null
}
</FormControl>
</Typography>
<Grid container spacing={6}>
{albumList}
</Grid>
</Container>
</React.Fragment>
)
}
}
export default Album
Card.js
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Card from '@material-ui/core/Card';
import CardActionArea from '@material-ui/core/CardActionArea';
import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent';
import CardMedia from '@material-ui/core/CardMedia';
import Typography from '@material-ui/core/Typography';
import Grid from '@material-ui/core/Grid';
import Button from '@material-ui/core/Button';
const useStyles = makeStyles({
card: {
maxWidth: 345,
},
media: {
height: 140,
},
});
export default function AlbumCard(props) {
const classes = useStyles();
let artist
let albumName
let artistHead
albumName = props.album.name
artist = props.album.artists.map((name, key) => {
if(albumName != name.name) {
return <Typography variant="body2" color="textSecondary" component="p" key={key}>
{name.name}
</Typography>
}
})
artistHead = props.album.artists.length > 1 ? 'Artists:' : 'Artist:'
const album = props.album
const page = "https://open.spotify.com/album/" + album.id
return(
<Grid item md={3}>
<Card className={classes.card}>
<CardActionArea>
<CardMedia
className={classes.card}
component="img"
alt={album.name}
height="140"
width="100"
image={album.images[0].url}
title={album.name}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
{album.name}
</Typography>
<Typography variant="body2" color="textSecondary" component="h3">
Release Date:
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
{album.release_date}
</Typography>
<Typography variant="body2" color="textSecondary" component="h3">
{artistHead}
</Typography>
{artist}
<Typography variant="body2" color="textSecondary" component="p">
{props.showMarkets && album.available_markets.map((c, i) => {
return <li key={i}>{c}</li>
})}
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
<a href={page} target="_blank">Album Page</a>
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
<a href={album.uri}>Open In App</a>
</Typography>
</CardContent>
</CardActionArea>
<Button
size="small"
color="primary"
onClick={props.handleShow}
>{props.showMarkets ? "Hide Markets" : "Show Markets"}</Button>
</Card>
</Grid>
)
}
我想我永远不会成为一个好的叙述者,但希望其他人对我的解决方案有所帮助