【问题标题】:onClick Just One Card Material UI ReactonClick Just One Card Material UI React
【发布时间】:2020-04-15 19:11:11
【问题描述】:

我有这个代码:

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 一张卡片的列表,但是当我点击任何按钮时,所有卡片的列表都会打开。 我无法解决这个问题。 我被困得太厉害了。 请帮帮我。 谢谢。

【问题讨论】:

    标签: javascript reactjs onclick material-ui


    【解决方案1】:

    好吧,我做到了。

    我通过从 Spotify API 返回的数据创建了状态,并将值设置为 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>
            )
    
      }
    

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

    【讨论】:

      猜你喜欢
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-13
      • 1970-01-01
      • 2021-06-06
      • 2021-04-23
      • 1970-01-01
      相关资源
      最近更新 更多