【问题标题】:React Material UI Cards w/ModalReact Material UI Cards w/Modal
【发布时间】:2021-10-08 06:04:23
【问题描述】:

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

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

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

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>

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

【问题讨论】:

    标签: reactjs material-ui modal-dialog card


    【解决方案1】:

    看来你的问题是你只使用一个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>
    
      ...
    

    【讨论】:

    • 感谢您的反馈。之前没有注意到这一点,我觉得有点傻,但是我将 Modal 组件放在“Campaigns”循环之外,一切都按预期工作。
    • @C-LosFX 啊,是的,那也行。 ? 干杯。
    猜你喜欢
    • 2019-05-25
    • 2020-06-04
    • 2019-05-25
    • 2019-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多