Событие React click button в списке всегда возвращает ссылку на последний элемент

#javascript #arrays #reactjs #jsx

Вопрос:

Я пытаюсь восстановить выбранный элемент в массиве элементов, у меня есть служба API, которая возвращает список из 5 заданий и страницу в React для отображения кандидатов. В отображаемой таблице из списка есть кнопка меню для каждой строки, когда я нажимаю на кнопку меню, она запускает событие handleMenuOpen и возвращает индекс выбранного задания, но при нажатии на элемент меню «Просмотреть кандидатов» запускается событие handleSeeApplicantsClick, и возвращаемое значение всегда равно 4 (индекс последнего задания) не могли бы вы помочь мне с этим?

Заранее спасибо

 import { useState, useEffect } from 'react';

import ApiService from '../../services/ApiService';

export default function Evaluation(props) {
    const [jobs, setJobs] = useState([]);
    const [selected, setSelected] = useState(null);
    const [anchorEl, setAnchorEl] = 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( async() => {
        if(!jobs?.length) loadJobs();
    }, []);

    const handleSeeApplicantsClick = (i) => {
        console.log(i);
        setAnchorEl(null);
    };

    const handleMenuOpen = (e, i) => {
        console.log(i);
        setAnchorEl(e?.currentTarget);
    }

    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, i) }>
                                <MenuIcon />
                            </IconButton>
                            <Menu anchorEl={anchorEl} open={ Boolean(anchorEl) } onClose={() => handleMenuOpen(null)}>
                                <MenuItem onClick={ (ex) => { handleSeeApplicantsClick(i) }}>See applicants</MenuItem>
                            </Menu>
                        </TableCell>
                    </TableRow> )}
                </TableBody>
            </Table>
        </TableContainer>
    </div>);
}

 

Редактировать:
Как и предполагалось, я изменил код следующим образом

  <IconButton onClick={ (e) => handleMenuOpen(e, j) }>
                                <MenuIcon />
                            </IconButton>
 

Но это не исправляет ошибку, всегда возвращается последний индекс.

Ответ №1:

Изменить handleMenuOpen(e, i) на handleMenuOpen(e, j)

i является конечным значением вашего предыдущего columns.map(x, i) , в то время как вы выполняете рендеринг с использованием jobs.map( (x, j))

Комментарии:

1. Я изменил переменную, но все равно возвращаю 4

Ответ №2:

изменить <IconButton onClick={ (e) => handleMenuOpen(e, i) }> на <IconButton onClick={ (e) => handleMenuOpen(e, j) }>

Комментарии:

1. Хотя этот код может дать ответ на вопрос, предоставление дополнительного контекста относительно того, почему и/или как этот код отвечает на вопрос, повышает его долгосрочную ценность.

2. Извините, я изменил эту переменную, но ошибка сохраняется.

Ответ №3:

измените параметр функции <IconButton onClick={ (e) => handleMenuOpen(e, i) }>

для <IconButton onClick={ (e) => handleMenuOpen(e, j) }> того, чтобы значение индекса карты было равно j, в вашем примере вам необходимо получить доступ из j…

  <TableBody>
                    {jobs.map( (x, j) => <TableRow key={x.id} >
                        <TableCell>
                            <Typography variant="body2">{ x.description }</Typography>
                        </TableCell>
                        <TableCell>
                            <IconButton onClick={ (e) => handleMenuOpen(e, i) }>
                                <MenuIcon />
                            </IconButton>
                            <Menu anchorEl={anchorEl} open={ Boolean(anchorEl) } onClose={() => handleMenuOpen(null)}>
                                <MenuItem onClick={ (ex) => { handleSeeApplicantsClick(i) }}>See applicants</MenuItem>
                            </Menu>
                        </TableCell>
                    </TableRow> )}
                </TableBody>

or for best approch you can handle this through by your unique id {x.id} if its unique