OttawaReactJS / talks

🗣 A place to propose future talks and gauging interest in React-related topics
12 stars 0 forks source link

React Material UI icon onclick not working properly #19

Closed narrasriram closed 7 months ago

narrasriram commented 3 years ago

I'm working on a react project where there will be a react material ui table component. Inside the table(10 reacords/rows in each page), the last element in every row is a Material UI MoreVert Icon

Expected Behaviour: When I click on the MoreVert icon in first row, it should show me the menu of options and when I click elsewhere the menu should be closed.

Current Behaviour: When I click the MoreVert Icon in the first row(or any of the rows in the page), it is showing me the options but when I click elsewhere in the page, the menu displayed on the current row is closing and at the same time a click event is automatically happening on the MoreVert icon in the 10th row(last row of the page) and the menu is opening for the 10th row.

Can anyone help me in achieving the expected behaviour

My code:

// File: XYZ.tsx

import Table from 'material-table';

.......
.......

const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);

const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {    
  setAnchorEl(event.currentTarget);
  };

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

.......
.......

const actions = [
    /* You can ignore this.
     {
      icon: () =>
        isMobile ? (
          <Assignment color="primary" />
        ) : (
          <Button
            className={classes.reportButton}
            size="small"
            variant="outlined"
            color="primary"
            startIcon={<Assignment />}
          >
            {t('nouns.report')}
          </Button>
        ),
      onClick: (event, rowData) =>
        history.push(`${PRIVATE.report}/${rowData.id}`),
    }, */
    tableRow => ({
      icon: () => (
        <Menu
          handleClick={handleClick}
          handleClose={handleClose}
          anchorEl={anchorEl}          
          validationDisabled={
            tableRow.validationStatus === ValidationStatus.Pending
          }
          onNewValidationClick={() => editIndividual(tableRow)}
          onDeleteClick={() => archiveIndividual(tableRow)}
        />
      ),
      onClick: handleClick as any,

      // Have tried these options but didn't work
      // onClose: handleClose,
      // onCancel: handleClose, 
    }),
  ];

.......
.......

return(

.......
.......

       <Table
          localization={localizationOptions}
          tableRef={tableRef}
          options={tableOptions}
          icons={tableIcons as any}
          title={upperFirst(t('nouns.individual', { count: 2 }))}
          columns={isMobile ? mobileColumns : columns}
          data={fetchData}
          actions={actions}
        />
);

My code for menu options

// File: Menu.tsx

import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { upperFirst } from 'lodash';
import { Menu as MaterialMenu, MenuItem, Box } from '@material-ui/core';
import { MoreVert, Add, Archive } from '@material-ui/icons';
import IconButton from '@material-ui/core/IconButton';

interface Props {
  validationDisabled: boolean;
  anchorEl: null | HTMLElement;
  handleClick: (value: React.MouseEvent<HTMLButtonElement>) => void;
  handleClose: () => void;
  onNewValidationClick: () => void;
  onDeleteClick: () => void;
}

const Menu: React.FC<Props> = ({  
  validationDisabled,
  anchorEl,
  handleClick,
  handleClose,
  onNewValidationClick,
  onDeleteClick,
}) => {

  const handleItemClick = (callback: () => void) => {
    callback();
    handleClose();
  };

  return (
    <Box>
      <MoreVert color="disabled"/>

      <MaterialMenu
        anchorEl={anchorEl}
        keepMounted
        open={Boolean(anchorEl)}
        onClose={handleClose}
      >
        <MenuItem
          disabled={validationDisabled}
          onClick={() => handleItemClick(onNewValidationClick)}
        >
          <Add fontSize="small" style={{ marginRight: 8 }} />
          {t('nouns.new_validation')}
        </MenuItem>
        <MenuItem onClick={() => handleItemClick(onDeleteClick)}>
          <Archive fontSize="small" style={{ marginRight: 8 }} />
          {upperFirst(t('verbs.archive'))}
        </MenuItem>
      </MaterialMenu>
    </Box>
  );
};

export default Menu;