【问题标题】:Material-ui v.1 - MenuItem passing outer index onClickMaterial-ui v.1 - MenuItem 传递外部索引 onClick
【发布时间】:2018-05-28 22:27:04
【问题描述】:

在我的组件中,我有一个Table,其中包含从一些自定义对象数组生成的行。在最后一个TableCell 我想要一个图标按钮,单击它会打开Menu 并带有一些MenuItem 操作(编辑和删除)。这是我的代码:

{folders.map(folder => {
return (
    <TableRow key={folder.id} >
        <TableCell>{folder.name}</TableCell>
        <TableCell>
            <IconButton
                onClick={this.handleFolderActionClick}>
                <MoreHoriz />
            </IconButton>
            <Menu onClose={this.handleFolderActionClose} >
                <MenuItem onClick={event => {onEditFolder(event, folder)}}>
                    <ListItemIcon>
                        <Edit />
                    </ListItemIcon>
                    <ListItemText inset primary="Edit" />
                </MenuItem>
                <MenuItem onClick={{event => onDeleteFolder(event, folder)}}>
                    <ListItemIcon>
                        <Delete />
                    </ListItemIcon>
                    <ListItemText inset primary="Delete" />
                </MenuItem>
            </Menu>
        </TableCell>
    </TableRow>
);
})}

onClick 事件始终传递数组中的最后一个文件夹元素,而不是映射到特定 TableRow 的那个。 我读过 MenuItem onClick 事件不应该以这种方式使用,但我不知道如何解决我的具体问题。我愿意接受任何建议。如何将外部map函数中的对象传递给ManuItemonClick事件?

编辑: Sandbox example

【问题讨论】:

    标签: javascript reactjs material-ui


    【解决方案1】:

    您可以尝试使用 currying 来避免内联菜单项处理程序并使它们更具可读性(并避免可能的与语法相关的错误,我相信您有)。您可以像这样定义处理程序:

    onEditFolder = folder => event => {
      // edit click handler
    }
    onDeleteFolder = folder => event => {
      // delete click handler
    }
    

    然后在您的渲染中使用它们(在您的folders.map 循环中),如下所示:

    <Menu onClose={this.handleFolderActionClose}>
      <MenuItem onClick={this.onEditFolder(folder)}>
        <ListItemIcon>
          <Edit />
        </ListItemIcon>
        <ListItemText inset primary="Edit" />
      </MenuItem>
      <MenuItem onClick={this.onDeleteFolder(folder)}>
        <ListItemIcon>
          <Delete />
        </ListItemIcon>
        <ListItemText inset primary="Delete" />
      </MenuItem>
    </Menu>
    

    您可以这样做,因为onEditFolder(folder) 根据其定义返回一个预期事件的函数。 onDeleteFolder(folder) 也一样。

    注意:我添加了 this 关键字作为这两个函数的前缀,假设它们是在使用它们的同一组件中定义的。如果您将它们作为道具传递,请进行相应修改。

    跟进: 该错误与映射无关,而是由于两个菜单都依赖相同的布尔值来切换打开或关闭,导致无论单击哪个项目都会显示最后一个菜单。

    我通过在 state 中创建一个 menus 数组来纠正这个问题,长度设置为列表大小,所有值初始化为 false(这是在 componentDidMount 生命周期方法中完成的)。更新了菜单打开和关闭以及关闭处理程序以传递列表项的索引,并将menus 数组中的值相应地更新为truefalse。每个Menu 组件的open 属性设置为menus 数组中的相应条目,以便根据相应值显示/隐藏菜单。

    最后,两个Menu 组件具有相同的id,我也更正了这一点。

    See working sandbox.

    【讨论】:

    • 不幸的是,当我尝试使用柯里化时,onEditFolder 函数中的文件夹参数未定义。知道为什么吗?
    • 如果它在函数中未定义,那么当您将它作为参数传递给映射循环中的该函数时,它就是未定义的。您是否尝试过在每次映射迭代开始时(在 return 语句之前)记录 folder 的值?
    • 看来我这边有问题,所以我创建了一个sandbox。如您所见,数组项被传递给函数,但它始终是数组中的最后一项。
    • 该错误与映射无关,而是由您使用相同的布尔值设置菜单的open 属性引起的。有关详细信息,请参阅更新的答案(包括修改后的沙箱)。
    猜你喜欢
    • 2019-11-13
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 2021-11-21
    • 1970-01-01
    • 2019-07-24
    相关资源
    最近更新 更多