You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React列表按钮点击事件总返回最后一个元素索引如何解决?

问题根源

你遇到的问题是两个错误共同导致的:

  1. 所有行的<Menu>组件共用同一个anchorEl状态,只要anchorEl不为空,所有行的菜单都会被同时渲染,你点击时触发的永远是最后一行渲染出来的菜单项事件
  2. 你只修改了IconButton点击事件里的索引参数,没有同步修改<MenuItem>点击事件里的索引参数,且没有单独存储当前选中的行索引

解决方案

按以下步骤修改代码即可:

  1. 新增一个状态存储当前打开菜单对应的行索引
  2. 只有当前行的索引和存储的打开索引一致时,才渲染对应的<Menu>组件,避免多个菜单同时挂载
  3. 同步修改<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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 17:06:01