onClick仅一张卡片材质的UI反应

时间:2019-12-24 20:42:12

标签: javascript reactjs onclick material-ui

我有此代码:

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 卡的列表,但是发生的情况是当我单击任意按钮时,所有卡的列表都在打开。 我无法解决这个问题。 我被卡住了。 请帮我。 谢谢。

1 个答案:

答案 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>
        )

  }

我想我永远不会成为一个好的叙述者,但希望其他人对我的解决方案有所帮助