反应 Material UI 卡片 w/Modal

React Material UI Cards w/Modal

我正在尝试配置此 React JS / Material UI 模态对话框,以便当用户单击卡片时,它会打开相应的 full-sized 图片(带有标题和副标题)。每张卡的数据都映射自 JSON 文件(通过 AXIOS)。

我可以打开模态 window,但它显示了模态中的所有卡片图像,并且它们相互堆叠。 handleOpen() 函数中的 console.log("SELECTED CAMPAIGN: ", selectedCampaign) 代码落后于单击一次...它实际上记录了在当前单击事件之前选择的 object。

我对功能组件和挂钩比较陌生,所以我知道我犯了一些简单而根本的错误...请帮我找出正确的设置方法:

const CampaignItems = ({campaigns, loading}) => {
    const classes = useStyles();

    const [open, setOpen] = useState(false);
    const [selectedCampaign, setSelectedCampaign] = useState();

    const handleOpen = (campaign) => {
        setSelectedCampaign(campaign);
        console.log("SELECTED CAMPAIGN: ", selectedCampaign);
        setOpen(true);
    };

    const handleClose = () => {
        setOpen(false);
    };

..................


<div>
                <GridContainer>
                    {campaigns && search(campaigns).map((campaign) => (
                        <GridItem key={campaign.id} xs={12} sm={6} md={4}>
                            <Card className={classes.root}>
                                <CardActionArea>
                                    <CardMedia
                                        component="img"
                                        alt={campaign.alt}
                                        height="140"
                                        image={campaign.image}
                                        title={campaign.title}
                                        onClick={() => handleOpen(campaign)}
                                    />
                                    <CardContent>
                                    <Typography gutterBottom variant="h5" component="h2">
                                        {campaign.title}
                                    </Typography>
                                        <Typography variant="body2" color="textSecondary" component="p">
                                            {campaign.subtitle}
                                        </Typography>
                                    </CardContent>
                                </CardActionArea>
                                <CardActions>
                                    <IconButton
                                        size="medium" 
                                        color="primary" 
                                        aria-label="More Information"
                                        onClick={() => handleOpen(campaign)}
                                    >
                                        <InfoIcon />
                                    </IconButton>

                                    <Modal
                                        className={classes.modal}
                                        open={open}
                                        onClose={handleClose}
                                        closeAfterTransition
                                        BackdropComponent={Backdrop}
                                        BackdropProps={{
                                            timeout: 500
                                        }}
                                    >
                                        <Fade 
                                            in={open}
                                        >
                                            <div className={classes.paper}>
                                                <h6>{campaign.title}</h6>
                                                <p>{campaign.subtitle}</p>
                                                <img src={campaign.image} />
                                            </div>
                                        </Fade>
                                    </Modal>

                                </CardActions>
                            </Card>
                        </GridItem>
                    ))}
                </GridContainer>
            </div>

..................

你的问题似乎是你只使用一个 open 状态来触发你的模式打开,所以它们都是同时触发打开的。

我建议改为使用您正在与之交互的卡片的 selectedCampaign,并使用与要打开的模式相匹配的活动 ID。

const CampaignItems = ({campaigns, loading}) => {
  ...

  const [selectedCampaign, setSelectedCampaign] = useState(null);

  const handleOpen = (campaign) => () => {
    setSelectedCampaign(selectedCampaign => 
      selectedCampaign.id === campaign.id ? null : campaign
    );
  };

  const handleClose = () => {
    setSelectedCampaign(null);
  };

  ...


  <div>
    <GridContainer>
      {campaigns && search(campaigns).map((campaign) => (
        <GridItem key={campaign.id} xs={12} sm={6} md={4}>
          <Card className={classes.root}>
            <CardActionArea>
              <CardMedia
                ...
                onClick={handleOpen(campaign)}
              />
              ...
            </CardActionArea>
            <CardActions>
              <IconButton
                ...
                onClick={handleOpen(campaign)}
              >
                ...
              </IconButton>

              <Modal
                ...
                open={selectedCampaign.id === campaign.id} // <-- check id match
                onClose={handleClose}
                ...
              >
                ...
              </Modal>

            </CardActions>
          </Card>
        </GridItem>
      ))}
    </GridContainer>
  </div>

  ...