React Material UI Cards w/Modal

Posted

技术标签:

【中文标题】React 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
                                        
                                        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>

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

【问题讨论】:

【参考方案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 啊,是的,那也行。 ? 干杯。

以上是关于React Material UI Cards w/Modal的主要内容,如果未能解决你的问题,请参考以下文章

React & Material-UI 分页 - 将 Material-UI 的组件连接到 React-Router

使用 React 和 Material-UI 的开源项目?

在 Material-UI 中使用 React 的 'ref' 属性

Material Design UI素材库React版--定制

React + Material-UI |如何创建水平滚动卡片?

为 SelectField 显示空白菜单项的正确方法是啥(material-ui,react)