reactjs - React Material UI Cards w/Modal
问题描述
I'm trying to configure this React JS / Material UI modal dialog so that when the user clicks on the card, it opens a corresponding full-sized image (with title and subtitle). Data for each card is mapped from a JSON file (via AXIOS).
I can get the modal window to open, but it is showing all of the card images in the modal and they are stacked on top of each other. The console.log("SELECTED CAMPAIGN: ", selectedCampaign)
code inside the handleOpen()
function is one click behind...it actually logs the object that was selected prior to the current click event.
I'm relatively new to functional components and hooks, so I know that I am making simple and fundamental mistakes...please help me figure out the proper way to set this up:
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>
...
推荐阅读
- sql - SQL - 具有平均值的数据输入
- mongodb - 如何使用 /data/db WT 文件恢复 mongodb
- django - drf-壮观的反向相关对象
- json - 从 LabelMe .xml 多边形到 coco 格式 .json
- javascript - 文本区域如何使用自定义组件显示与控制台中显示的内容不同的内容?
- c# - Unity 出现故障但不显示任何错误
- javascript - 如何使用本身在 Nodejs 中调用另一个异步方法的 Promise 从异步方法返回值?
- python - 在网页抓取时加载 Chrome 扩展程序
- python - 当按下按钮时,Tkinter 为 Entry 打印 None
- typescript - 我的 NestJs 异常拦截器似乎没有做任何事情