Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Material UI Menu not getting the correct ID

So basically I have this table that needs to have an action menu button. When it renders, it copies the last ID of the given array. I don't know what's the problem behind this mess actually. I've tried out various solutions and they did not tend to answer my problem.

Here's my actual code.

import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import {
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TablePagination,
  TableRow,
  TableSortLabel,
  Paper,
  Button,
  Menu,
  MenuItem
} from '@material-ui/core';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import ArrowDropUpIcon from '@material-ui/icons/ArrowDropUp';

import { useStyles } from './table-started.styles';

function descendingComparator(a, b, orderBy) {
  if (b[orderBy] < a[orderBy]) {
    return -1;
  }
  if (b[orderBy] > a[orderBy]) {
    return 1;
  }
  return 0;
}

function getComparator(order, orderBy) {
  return order === 'desc'
    ? (a, b) => descendingComparator(a, b, orderBy)
    : (a, b) => -descendingComparator(a, b, orderBy);
}

function stableSort(array, comparator) {
  const stabilizedThis = array.map((el, index) => [el, index]);
  stabilizedThis.sort((a, b) => {
    const order = comparator(a[0], b[0]);
    if (order !== 0) return order;
    return a[1] - b[1];
  });
  return stabilizedThis.map((el) => el[0]);
}

const headCells = [
  { id: 'title', disablePadding: false, label: 'Title' },
  { id: 'author_name', disablePadding: false, label: 'Author(s)' },
  { id: 'created_at', disablePadding: false, label: 'Started' },
  { id: 'actions', disablePadding: false, label: 'Actions' }
];

function EnhancedTableHead(props) {
  const tableStyles = useStyles();
  const { classes, order, orderBy, onRequestSort } = props;
  const createSortHandler = (property) => (event) => {
    onRequestSort(event, property);
  };

  return (
    <TableHead className={tableStyles.tableContainer}>
      <TableRow>
        {headCells.map((headCell) => (
          <TableCell
            key={headCell.id}
            className={tableStyles.tableTitle}
            align='left'
            padding='default'
            sortDirection={orderBy === headCell.id ? order : false}
          >
            <TableSortLabel
              className={tableStyles.tableTitle}
              active={orderBy === headCell.id}
              direction={orderBy === headCell.id ? order : 'asc'}
              onClick={createSortHandler(headCell.id)}
            >
              {headCell.label}
              {orderBy === headCell.id ? (
                <span className={classes.visuallyHidden}>
                  {order === 'desc' ? 'sorted descending' : 'sorted ascending'}
                </span>
              ) : null}
            </TableSortLabel>
          </TableCell>
        ))}
      </TableRow>
    </TableHead>
  );
}

EnhancedTableHead.propTypes = {
  classes: PropTypes.object.isRequired,
  numSelected: PropTypes.number.isRequired,
  onRequestSort: PropTypes.func.isRequired,
  onSelectAllClick: PropTypes.func.isRequired,
  order: PropTypes.oneOf(['asc', 'desc']).isRequired,
  orderBy: PropTypes.string.isRequired,
  rowCount: PropTypes.number.isRequired
};

const TableStarted = ({ ctrResults }) => {
  const classes = useStyles();
  const [order, setOrder] = useState('asc');
  const [orderBy, setOrderBy] = useState('calories');
  const [selected, setSelected] = useState([]);
  const [page, setPage] = useState(0);
  const [rowsPerPage, setRowsPerPage] = useState(5);
  const [rows, setRows] = useState([]);

  useEffect(() => {
    if (ctrResults) {
      console.log(ctrResults);
      setRows(ctrResults);
    }
  }, [ctrResults]);

  const handleRequestSort = (event, property) => {
    const isAsc = orderBy === property && order === 'asc';
    setOrder(isAsc ? 'desc' : 'asc');
    setOrderBy(property);
  };

  const handleSelectAllClick = (event) => {
    if (event.target.checked) {
      const newSelecteds = rows.map((n) => n.name);
      setSelected(newSelecteds);
      return;
    }
    setSelected([]);
  };

  const handleClick = (event, name) => {
    const selectedIndex = selected.indexOf(name);
    let newSelected = [];

    if (selectedIndex === -1) {
      newSelected = newSelected.concat(selected, name);
    } else if (selectedIndex === 0) {
      newSelected = newSelected.concat(selected.slice(1));
    } else if (selectedIndex === selected.length - 1) {
      newSelected = newSelected.concat(selected.slice(0, -1));
    } else if (selectedIndex > 0) {
      newSelected = newSelected.concat(
        selected.slice(0, selectedIndex),
        selected.slice(selectedIndex + 1)
      );
    }

    setSelected(newSelected);
  };

  const handleChangePage = (event, newPage) => {
    setPage(newPage);
  };

  const handleChangeRowsPerPage = (event) => {
    setRowsPerPage(parseInt(event.target.value, 10));
    setPage(0);
  };

  const isSelected = (name) => selected.indexOf(name) !== -1;

  const emptyRows =
    rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);

  const [anchorEl, setAnchorEl] = React.useState(null);

  const handleMenuClick = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  const goToEdit = (id, e) => {
    e.preventDefault();
    window.location.href = `/submission/results/${id}`;
  };

  return (
    <div className={classes.root}>
      <Paper className={classes.paper}>
        <TableContainer>
          <Table
            className={classes.table}
            aria-labelledby='tableTitle'
            size='medium'
            aria-label='enhanced table'
          >
            <EnhancedTableHead
              classes={classes}
              numSelected={selected.length}
              order={order}
              orderBy={orderBy}
              onSelectAllClick={handleSelectAllClick}
              onRequestSort={handleRequestSort}
              rowCount={rows.length}
            />
            <TableBody className={classes.tableBody}>
              {stableSort(rows, getComparator(order, orderBy))
                .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
                .map((row, index) => {
                  const isItemSelected = isSelected(row._id.$oid);
                  const labelId = `enhanced-table-checkbox-${index}`;

                  let author_name = row.author_first_name
                    ? row.author_first_name
                    : '';

                  author_name = row.author_last_name
                    ? author_name + ' ' + row.author_last_name
                    : 'N/A';

                  return (
                    <TableRow className={classes.tableRow}>
                      <TableCell
                        className={classes.tableData}
                        padding='default'
                        component='th'
                        id={labelId}
                        scope='row'
                      >
                        {row.title}
                      </TableCell>
                      <TableCell
                        scope='row'
                        className={classes.tableData}
                        align='left'
                      >
                        {author_name}
                      </TableCell>
                      <TableCell
                        scope='row'
                        className={classes.tableData}
                        align='left'
                      >
                        {row.created_at.substring(0, 10)}
                      </TableCell>
                      <TableCell
                        scope='row'
                        className={classes.tableData}
                        align='left'
                      >
                        <Menu
                          id='actions'
                          anchorEl={anchorEl}
                          keepMounted
                          open={Boolean(anchorEl)}
                          onClose={handleClose}
                        >
                          <MenuItem onClick={(e) => goToEdit(row._id.$oid, e)}>
                            Edit
                          </MenuItem>
                          <MenuItem onClick={handleClose}>Delete</MenuItem>
                        </Menu>
                        <Button
                          aria-controls='simple-menu'
                          aria-haspopup='true'
                          onClick={handleMenuClick}
                          className={classes.menuButton}
                          endIcon={
                            anchorEl ? (
                              <ArrowDropUpIcon />
                            ) : (
                              <ArrowDropDownIcon />
                            )
                          }
                        >
                          Actions
                        </Button>
                      </TableCell>
                    </TableRow>
                  );
                })}
              {emptyRows > 0 && (
                <TableRow style={{ height: 53 * emptyRows }}>
                  <TableCell colSpan={6} />
                </TableRow>
              )}
            </TableBody>
          </Table>
        </TableContainer>
        <TablePagination
          rowsPerPageOptions={[5, 10, 20]}
          component='div'
          count={rows.length}
          rowsPerPage={rowsPerPage}
          page={page}
          onChangePage={handleChangePage}
          onChangeRowsPerPage={handleChangeRowsPerPage}
        />
      </Paper>
    </div>
  );
};

export default TableStarted;

and here's the sample Menu:

Menu Sample

but it gets the last rows array's row._id.$oid in each row. How can I get each unique's ID?

When I do console.log, the row._id.$oid is being replaced.

Row ID Console.log

like image 562
luffypirates Avatar asked Oct 24 '25 09:10

luffypirates


1 Answers

It seems that each row is sharing the same menu items. You can validate this if you add a new item that will display the current row id. This might be because you are reusing anchorEl.

...
<MenuItem onClick={(e) => goToEdit(row._id.$oid, e)}>Edit</MenuItem>
<MenuItem onClick={handleClose}>Delete</MenuItem>
<MenuItem>{row._id.$oid}</MenuItem> // this will display the last row's id

A possible solution would be to create a separate component for your row menu items.

// RowMenu.js
...

export function RowMenu({ row, goToEdit }) {
  const [anchorEl, setAnchorEl] = React.useState(null);
  const classes = useStyles();

  const handleMenuClick = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  return (
    <>
      <Menu
        id={`actions-${row._id.$oid}`}
        anchorEl={anchorEl}
        keepMounted
        open={Boolean(anchorEl)}
        onClose={handleClose}
      >
        <MenuItem onClick={(e) => goToEdit(row._id.$oid, e)}>Edit</MenuItem>
        <MenuItem onClick={handleClose}>Delete</MenuItem>
        <MenuItem>{row._id.$oid}</MenuItem>
      </Menu>
      <Button
        aria-controls="simple-menu"
        aria-haspopup="true"
        onClick={handleMenuClick}
        className={classes.menuButton}
        endIcon={anchorEl ? <ArrowDropUpIcon /> : <ArrowDropDownIcon />}
      >
        Actions
      </Button>
    </>
  );
}

Edit keen-dhawan-l6fru

like image 133
bertdida Avatar answered Oct 26 '25 01:10

bertdida



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!