I'm having an issue with my Material UI <Menu>. Basically, I'm mapping over a <Card> to display some data and interface functionality. I'm trying to add a <IconButton> on each card. Once, clicked, the button opens a menu. Currently the issue I'm facing is, when I click on the IconButton, all menu's open up on top of each other (due to mapping over menu items with the same state prop).
<CardHeader
action={
<>
<IconButton
onClick={handleClick}
aria-label="settings">
<MoreVertIcon />
</IconButton>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Edit </MenuItem>
<MenuItem onClick={handleClose}>Delete</MenuItem>
</Menu>
</>
}
/>
You can tell due to the large shadow behind the Menu, that's not CSS by choice... thats all my menus stacked up from my <Card> component. I know the culprit is having one open close state property. Is there any "quickfix" to this solution? I can't hardcode the states themselves.
Here is the rest of the code where I return my map function that produces <Card>. Please check my <CardHeader>. Note that I have two <CardHeaders>, that's because I have a conditional that dictates which CardHeader to use for the card.
const UserBuckets = (props) => {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
if (!buckets || buckets.length === 0) return <p>Can not find any buckets, make one below!</p>;
return (
<React.Fragment style=>
<Container style= maxWidth="md" component="main">
<Grid container spacing={5} alignItems="stretch">
{buckets.map((bucket) =>
{
return (
<Grid item key={bucket.id} xs={12} sm={6} md={4} lg={4}>
<Card
className={classes.root}
classes=
onMouseOver={() => setState({ shadow: 3 })}
onMouseOut={() => setState({ shadow: 1 })}
zdepth={state.shadow}
style=
>
{(!bucket || bucket.stock_list === null) &&
<CardHeader className={classes.bucketTitle} classes=
title={
<>
<Link
color="textPrimary"
href={'dash/' + bucket.slug}
className={classes.link}
style=
>
{bucket.name.substr(0, 50)}
</Link>
</>
}
subheader="Add Stocks to get started!"
action={
<>
<IconButton
onClick={handleClick}
aria-label="settings">
<MoreVertIcon />
</IconButton>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
style=
elevation={0}
>
<MenuItem onClick={handleClose}>Edit </MenuItem>
<MenuItem onClick={handleClose}>Delete</MenuItem>
</Menu>
</>
}
/>}
{bucket && bucket.stock_list != null &&
<CardHeader className="cardHeaderBucket"
title={bucket.name.substr(0, 20)}
subheader={bucket.about}
action={
<>
<IconButton
onClick={handleClick}
aria-label="settings">
<MoreVertIcon />
</IconButton>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Edit </MenuItem>
<MenuItem onClick={handleClose}>Delete</MenuItem>
</Menu>
</>
}
style=
/>}
<CardContent className={classes.cardContent}>
{(!bucket || bucket.bucket_pos_neg === null) &&
<p style= >
Your Bucket is empty...
</p>}
{bucket && bucket.bucket_pos_neg != null &&
<div className={classes.bucketText}>
<Grid>
<Typography variant="subtitle1" color="textSecondary">
{/* {bucket.stock_list.join(",").substr(0, 15)}... */}
{"Total Stocks: " + bucket.stock_count}
</Typography>
<Typography variant="overline">
Return Donut
</Typography>
<BucketDoughnutDisplay data={bucket.bucket_pos_neg} />
</Grid>
</div>
}
</CardContent>
</Card>
</Grid>
);
})}
</Grid>
</Container>
</React.Fragment>
);
};
How can I fix my Menu to be unique for each individual card? My one state for my approach is causing major issues. Thank you for the help.
EDIT: Right now the menu is not popping up and no consle errors to work from. I have made the second round of revision. Please see this code
const UserBuckets = (props) => {
const [anchorEl, setAnchorEl] = React.useState(null);
const [currentIndex, setCurrentIndex] = useState(0);
const handleClick = (index) => (event) => {
setAnchorEl(event.currentTarget);
setCurrentIndex(index);
};
const handleClose = () => {
setAnchorEl(null);
};
const classes = useStyles();
if (!buckets || buckets.length === 0) return <p>Can not find any buckets, make one below!</p>;
return (
<React.Fragment>
<Container style= maxWidth="md" component="main">
<Grid container spacing={5} alignItems="stretch">
{buckets.map((bucket, index) =>
{
return (
<Grid item key={bucket.id} xs={12} sm={6} md={4} lg={4}>
<Card
className={classes.root}
classes=
onMouseOver={() => setState({ shadow: 3 })}
onMouseOut={() => setState({ shadow: 1 })}
zdepth={state.shadow}
style=
>
{(!bucket || bucket.stock_list === null) &&
<CardHeader className={classes.bucketTitle} classes=
title={
<>
<Link
color="textPrimary"
href={'dash/' + bucket.slug}
className={classes.link}
style=
>
{bucket.name.substr(0, 50)}
</Link>
</>
}
subheader="Add Stocks to get started!"
action={
<>
<IconButton
onOpen={handleClick(index)}
aria-label="settings">
<MoreVertIcon />
</IconButton>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl) && currentIndex}
onClose={handleClose}
style=
elevation={0}
>
<MenuItem onClick={handleClick(index)}>Edit </MenuItem>
<MenuItem onClick={handleClick(index)}>Delete</MenuItem>
</Menu>
</>
}
/>}
{bucket && bucket.stock_list != null &&
<CardHeader className="cardHeaderBucket"
title={bucket.name.substr(0, 20)}
subheader={bucket.about}
action={
<>
<IconButton
onOpen={handleClick(index)}
aria-label="settings">
<MoreVertIcon />
</IconButton>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl) && currentIndex}
onClose={handleClose}
>
<MenuItem onClick={handleClick(index)}>Edit </MenuItem>
<MenuItem onClick={handleClick(index)}>Delete</MenuItem>
</Menu>
</>
}
style=
/>}
<CardContent className={classes.cardContent}>
{(!bucket || bucket.bucket_pos_neg === null) &&
<p style= >
Your Bucket is empty...
</p>}
{bucket && bucket.bucket_pos_neg != null &&
<div className={classes.bucketText}>
<Grid>
<Typography variant="subtitle1" color="textSecondary">
{/* {bucket.stock_list.join(",").substr(0, 15)}... */}
{"Total Stocks: " + bucket.stock_count}
</Typography>
<Typography variant="overline">
Return Donut
</Typography>
<BucketDoughnutDisplay data={bucket.bucket_pos_neg} />
</Grid>
</div>
}
</CardContent>
</Card>
</Grid>
);
})}
</Grid>
</Container>
</React.Fragment>
);
};
from Mapping over Menu objects causing multiple menus to open due to state

No comments:
Post a Comment