Open1
[React, Material UI] MenuItemにうまくデータを渡せなかった話

やりたかったこと
- 一覧表示されたデータがあり、各行に3点のアイコン(以下3点アイコン)がある。
- 3点アイコンをクリックすると 編集/削除ボタンが表示される。
- 削除ボタン押下時に該当行を削除
メンバーのスキーマ定義
schema.graphql
type Member @model {
id: ID!
name: String!
tel: String!
address: String!
}
...が!
選択した行ではない行が削除される事象が発生
不具合の原因
3点アイコンクリック時に行のIDを渡していなかったため、
全行分のメニューが開き、重なって表示されていた
→どの行からメニューを開いても、操作できるメニューは最前面に表示されている行のメニューだった
うまく行った実装
変更点
-
currentRow
: 現在の行を管理する -
handleOpenMenu()
: 3点アイコン押下時に現在の行のデータをcurrentRow
にセットする -
handleCloseMenu()
: メニューが閉じられるときはcurrentRow
を null に戻す
Listtable.tsx
const ITEM_HEIGHT = 48
const ListTable = (props) => {
const classes = useStyles()
const clientEditRouting = (url) => {
Router.push(url)
}
const currentURL = useRouter()
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null)
+ const [currentRow, setCurrentRow] = React.useState(null)
const handleDelete = (e, row) => {
e.preventDefault()
onDeleteClicked(row.id)
}
const onDeleteClicked = async (id) => {
const result = (await API.graphql(
graphqlOperation(updateMember, {
input: {
id: id,
deletedAt: Date.now().toString(),
},
})
)) as GraphQLResult<UpdateMemberMutation>
window.location.reload()
}
- const handleOpenMenu = (event: React.MouseEvent<HTMLElement>) => {
- // row.id を指定していないので全行のメニューアイテムが開いてしまう
- setAnchorEl(event.currentTarget)
- }
- const handleCloseMenu = () => {
- setAnchorEl(null)
- }
+ const handleOpenMenu = (event: React.MouseEvent<HTMLElement>, row) => {
+ setAnchorEl(event.currentTarget)
+ setCurrentRow(row)
+ }
+ const handleCloseMenu = () => {
+ setAnchorEl(null)
+ setCurrentRow(null)
+ }
return (
<TableContainer component={Paper}>
<Table className={classes.table} aria-label="simple table">
<TableHead>
<TableRow >
<TableCell className={classes.tableRow}>名称</TableCell>
<TableCell className={classes.tableRow}>住所</TableCell>
<TableCell className={classes.tableRow}>電話番号</TableCell>
<TableCell className={classes.tableRow}></TableCell>
</TableRow>
</TableHead>
<TableBody>
{props.data.map((row) => (
<TableRow className={classes.button} key={row.id}>
<TableCell>{row.name}</TableCell>
<TableCell>{row.address}</TableCell>
<TableCell>{row.tel}</TableCell>
<TableCell>
<IconButton
aria-label="more"
aria-controls="long-menu"
aria-haspopup="true"
onClick={(event) => handleOpenMenu(event, row)}
className={classes.morevertIcon}
>
<MoreVertIcon />
</IconButton>
<Menu
id="long-menu"
anchorEl={anchorEl}
keepMounted
- open={open}
+ open={currentRow === row}
onClose={() => handleCloseMenu()}
PaperProps={{
style: {
maxHeight: ITEM_HEIGHT * 4.5,
width: '20ch',
}
}}
>
<MenuItem key='Edit' onClick={() => clientEditRouting(`${currentURL.pathname}/edit/${row.id}`)}>
<ListItemIcon>
<EditIcon fontSize='small' />
</ListItemIcon>
<Typography variant="inherit">編集</Typography>
</MenuItem>
<MenuItem key='Delete' onClick={e => handleDelete(e, row)}>
<ListItemIcon>
<DeleteIcon fontSize='small' />
</ListItemIcon>
<Typography variant="inherit">削除</Typography>
</MenuItem>
</Menu>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
)
}
export default ListTable
結果
想定通り指定した行を削除できた。
参考
- 3点アイコンを使った実装
- 不具合の解決のヒントになった Stack Overflow