3

I am trying to create a React Material Popover(https://material-ui.com/api/popover/) element, to be shown when user hovers mouse over a TableRow (https://material-ui.com/api/table-row/), and to be hidden when user hovers mouse out of the TableRow.

What I have already tried :

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


const handlePopoverClose = event => {
    setAnchorEl(null);
  };

const open = Boolean(anchorEl);

. . .

<TableRow
   selected={props.selected === key ? true : false}
   hover={true}
   key={key} className={classes.tableBodyRow}
   onClick={() => props.onSelectChange(key, prop[0], prop[1])}
   onMouseOver={handlePopoverOpen}
   onMouseOut={handlePopoverClose}            
>

. . .

<Popover
    id="mouse-over-popover"
    open={open}
    anchorEl={anchorEl}
    anchorOrigin={{
      vertical: 'bottom',
      horizontal: 'center',
    }}
    transformOrigin={{
      vertical: 'top',
      horizontal: 'left',
    }}
    onClose={handlePopoverClose}
  >
    I use Popover
  </Popover>

Popover appears when mouse is hovered over the TableRow, but then it keeps blinking like there is an infinite loop of onMouseOver() and onMouseOut(). I have been investigating this issue for hours and I cant find the explanation of this issue. I would appreciate if someone could help!

Here is a code live demo: https://codesandbox.io/s/heuristic-banach-071f3?fontsize=14&hidenavigation=1&theme=dark

NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
sonan
  • 91
  • 2
  • 12
  • Could you make it an online demo? Which may help others catch up with the problem you are facing quickly! – keikai Mar 21 '20 at 18:19
  • Ok! I'll try to demonstrate it. – sonan Mar 21 '20 at 23:45
  • This issue is happening to me right now on MouseEnter and MouseLeave events directly in React but it's just happening on chrome I tested on Firefox and the issue is not happening it seems to have an infinite loop on MouseEnter and MouseLeave events. if anyone knows how to resolve it I'll appreciate it. – cristian.nieto.dev Apr 28 '21 at 04:06
  • @cristian.nieto.dev I remember that I never found a solution on this, so I decided to change design. But as I can see now, the link provided on the sandbox above works. Check it out, maybe it was an issue of Google chrome's internals – sonan Apr 30 '21 at 13:53

2 Answers2

2

Did you check the 'Mouse over interaction' section at https://material-ui.com/components/popover/?

I can't see the rest of your code, so difficult to advice on the exact changes you need to make, but your solution is a bit different from the example:

<Typography
  aria-owns={open ? 'mouse-over-popover' : undefined}
  aria-haspopup="true"
  onMouseEnter={handlePopoverOpen}
  onMouseLeave={handlePopoverClose}
>
  Hover with a Popover.
</Typography>

ADDED:

After seeing the whole code, I would make these changes:

  1. Make your tableData array an array of objects rather than an array of arrays
const tableData = [{name: "Nick", age: 15}, {name: "George", age: 10}, {name: "John", age: 11}];
  1. Change your code inside tableBody to reflect this
<TableBody>
  {tableData.map(data => {
    return (
      <TableRow
        key={data.name}
        hover={true}
        aria-haspopup="true"
        onMouseOver={handlePopoverOpen}
        onMouseOut={handlePopoverClose}
      >
        <TableCell>{data.name}</TableCell>
        <TableCell>{data.age}</TableCell>
      </TableRow>
    )
  })}
</TableBody>

NOTE: the key has to be unique, so no duplicate names. Best option is to add an unique id to the object and use it as the key.

{id: 1, name: "Nick", age: 15}

Then test the popover!

NinaW
  • 638
  • 3
  • 7
  • Yes, that's tjhe template I followed to contruct my implementation. onMouseEnter and onMouseLeave produce the same result. Popover component shows up and disappears in an infite loop. – sonan Mar 21 '20 at 23:47
  • Ok, I would need to see more of your code to test. You do have a state for `AnchorEl` right? – NinaW Mar 21 '20 at 23:59
  • I use a React hook for anchorEl : const [anchorEl, setAnchorEl] = useState(null); And the two functions: `handlePopoverOpen => (event) { setAnchorEl(event.target)}` `handlePopoverClose =>{setAnchorEl(null)}` – sonan Mar 22 '20 at 01:05
  • I'll wait for the demo, but check that you are using `setAnchorEl(event.currentTarget)` as in your example. – NinaW Mar 22 '20 at 01:38
  • I've added a section to my answer after seeing the demo : ) – NinaW Mar 22 '20 at 13:40
  • I have tested it with array of objects. Same thing happens. Popover appears and disappears imidiately. Maybe a problem with material-ui TableRow and mouse events? – sonan Mar 22 '20 at 14:10
  • Yes, it seems to be a bit sketchy - works sometimes, sometimes not. There is console warning at the demo (at the bottom under the display), that says the issue is with refs in strict mode. It advices to add a ref directly to the element you want to reference. – NinaW Mar 22 '20 at 14:51
  • Check this sandbox https://codesandbox.io/s/5vwyjr35pl for a workaround. – NinaW Mar 22 '20 at 15:27
  • The workaround relates to this issue https://github.com/mui-org/material-ui/issues/15705 – NinaW Mar 22 '20 at 15:49
  • Thanks a lot for your help and your time!! I really appreciate it. I am working on an workaround in which user opens the popover with right-click and closes it with a button. This seems to work until now. I am going to search for similar issues on material-ui github page and I maybe open a new one for this issue. – sonan Mar 22 '20 at 16:23
  • Sounds good. Having a button or some indication to opt for the popover seems the best way to go. – NinaW Mar 23 '20 at 19:57
2

After settings pointerEvents to none, it started working properly.

sx={{
       pointerEvents: 'none',
}}

Full example

<Popover
          open={avatarOpen}
          anchorEl={anchorEl}
          onClose={handlePopoverClose}
          sx={{
              pointerEvents: 'none',
          }}
</Popover>
Jaanus
  • 16,161
  • 49
  • 147
  • 202