首页 > 解决方案 > 映射 Menu 对象导致多个菜单因状态而打开

问题描述

我的 Material UI 有问题<Menu>。基本上,我正在映射 a<Card>以显示一些数据和界面功能。我正在尝试<IconButton>在每张卡上添加一个。单击一次,该按钮将打开一个菜单。目前我面临的问题是,当我单击 IconButton 时,所有菜单都在彼此之上打开(由于映射具有相同 state 属性的菜单项)。

                                 <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>
                                        </>
                                    }
                                  />

在此处输入图像描述

由于菜单后面的阴影很大,您可以看出,这不是 CSS 的选择……这就是我所有的菜单都从我的<Card>组件中堆叠起来的。我知道罪魁祸首是拥有一个打开关闭状态的财产。这个解决方案有什么“快速修复”吗?我不能对状态本身进行硬编码。

这是我返回生成的 map 函数的其余代码<Card>。请检查我的<CardHeader>. 请注意,我有两个<CardHeaders>,那是因为我有一个条件来指示卡片使用哪个 CardHeader 。

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={{width:"90%"}}>
            <Container style={{width:"90%"}} 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={{ root: state.raised ? classes.cardHovered : "" }}
                            onMouseOver={() => setState({ shadow: 3 })}
                            onMouseOut={() => setState({ shadow: 1 })}
                            zdepth={state.shadow}
                            style={{  height: "100%", borderRadius:"30px"}}
                            >
                            {(!bucket || bucket.stock_list === null) &&
                                <CardHeader className={classes.bucketTitle} classes={{ title: classes.bucketTitle }}
                                        title={
                                            <>
                                            <Link 
                                                color="textPrimary"
                                                href={'dash/' + bucket.slug}
                                                className={classes.link}
                                                style={{ textDecoration: 'none' }}
                                            >
                                                {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={{boxShadow: 'none'}}
                                                    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={{margin:0}}
                                />}
                                
                                <CardContent className={classes.cardContent}>
                                    {(!bucket || bucket.bucket_pos_neg === null) &&
                                    <p style={{ textAlign: "center" }} >
                                        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>
    );
};

我怎样才能让我Menu的每张卡都是独一无二的?我的方法的一个状态是引起重大问题。感谢您的帮助。


编辑:现在菜单没有弹出,也没有控制台错误。我已经进行了第二轮修改。请看这段代码

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={{width:"90%"}} 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={{ root: state.raised ? classes.cardHovered : "" }}
                            onMouseOver={() => setState({ shadow: 3 })}
                            onMouseOut={() => setState({ shadow: 1 })}
                            zdepth={state.shadow}
                            style={{  height: "100%", borderRadius:"30px"}}
                            >
                            {(!bucket || bucket.stock_list === null) &&
                                <CardHeader className={classes.bucketTitle} classes={{ title: classes.bucketTitle }}
                                        title={
                                            <>
                                            <Link 
                                                color="textPrimary"
                                                href={'dash/' + bucket.slug}
                                                className={classes.link}
                                                style={{ textDecoration: 'none' }}
                                            >
                                                {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={{boxShadow: 'none'}}
                                                    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={{margin:0}}
                                />}
                                
                                <CardContent className={classes.cardContent}>
                                    {(!bucket || bucket.bucket_pos_neg === null) &&
                                    <p style={{ textAlign: "center" }} >
                                        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>
    );
};

标签: javascriptreactjsmaterial-ui

解决方案


尝试将当前索引与您的打开状态一起存储,以识别当前Menu要打开的状态:

const [currentIndex, setCurrentIndex] = useState(0);
const handleClick = (index) => (event) => {
  setAnchorEl(event.currentTarget);
  setCurrentIndex(index);
};
buckets.map((bucket, index) => (
  <>
    <Grid>
      <Menu open={Boolean(anchorEl) && currentIndex} {...props} />
    </Grid>
    <IconButton onOpen={handleClick(index)}/>
  </>
))

推荐阅读