React列表按钮点击事件总返回最后一个元素索引如何解决?
问题根源
你遇到的问题是两个错误共同导致的:
- 所有行的
<Menu>组件共用同一个anchorEl状态,只要anchorEl不为空,所有行的菜单都会被同时渲染,你点击时触发的永远是最后一行渲染出来的菜单项事件 - 你只修改了
IconButton点击事件里的索引参数,没有同步修改<MenuItem>点击事件里的索引参数,且没有单独存储当前选中的行索引
解决方案
按以下步骤修改代码即可:
- 新增一个状态存储当前打开菜单对应的行索引
- 只有当前行的索引和存储的打开索引一致时,才渲染对应的
<Menu>组件,避免多个菜单同时挂载 - 同步修改
<MenuItem>点击事件的传参为当前行的j
修正后的完整代码
import { useState, useEffect } from 'react'; import ApiService from '../../services/ApiService'; // 注意自行引入你代码中用到的Paper、Table系列组件、IconButton、Menu、MenuItem、MenuIcon、Typography等依赖 export default function Evaluation(props) { const [jobs, setJobs] = useState([]); const [selected, setSelected] = useState(null); const [anchorEl, setAnchorEl] = useState(null); // 新增状态存储当前打开菜单对应的行索引 const [openMenuIndex, setOpenMenuIndex] = useState(null); const columns = [ {label: 'Description', minWidth: 220, width: 200,}, {label: '', minWidth: 20, width: 20}, ]; const loadJobs = async() => { const result = await ApiService.get('/u/jobs'); setJobs(result.data || []); }; const loadSelectedJob = async(jobId) => { const result = await ApiService.get('/u/job/'+jobId); setSelected(result); }; useEffect(() => { // 修正原代码useEffect直接传入async函数的不规范写法 const init = async () => { if(!jobs?.length) await loadJobs(); } init(); }, []); const handleSeeApplicantsClick = (i) => { console.log(i); setAnchorEl(null); setOpenMenuIndex(null); }; const handleMenuOpen = (e, i) => { console.log(i); setAnchorEl(e?.currentTarget); setOpenMenuIndex(i); } const handleMenuClose = () => { setAnchorEl(null); setOpenMenuIndex(null); } return (<div> <TableContainer component={Paper}> <Table stickyHeader> <TableHead> <TableRow> { columns.map((x, i) => <TableCell key={i}>{ x.label }</TableCell>) } </TableRow> </TableHead> <TableBody> {jobs.map( (x, j) => <TableRow key={x.id} > <TableCell> <Typography variant="body2">{ x.description }</Typography> </TableCell> <TableCell> <IconButton onClick={ (e) => handleMenuOpen(e, j) }> <MenuIcon /> </IconButton> {/* 仅当前行是打开状态时才渲染菜单,避免多菜单同时挂载 */} {openMenuIndex === j && <Menu anchorEl={anchorEl} open={ Boolean(anchorEl) } onClose={handleMenuClose}> <MenuItem onClick={ (ex) => { handleSeeApplicantsClick(j) }}>See applicants</MenuItem> </Menu>} </TableCell> </TableRow> )} </TableBody> </Table> </TableContainer> </div>); }
内容的提问来源于stack exchange,提问作者mapr
相关产品推荐
相关产品推荐

