#Identify React component that was right-clicked

8 messages · Page 1 of 1 (latest)

hollow plinth
#

I'd like to be able to identify which React component was right-clicked, so I can make my custom context menu useful.

I'm using react-contexify to manage most of it, and I got everything working, but I'm having getting it to identify exactly which thing was clicked. While prototyping, I was using the following code:

const MyContextArea = () => {
  const {show} = useContextMenu({
    id: 'my-menu-id',
  });
  const handleContextMenu = (event: any) => {
    console.log('handleContextMenu:', event);
    show({
      event,
      props: {
        target: event.target?.dataset?.pageId,
      },
    });
  }
  const handleItemClick = ({id = '', event = {}, props = {}}) => {
    console.log('Perform action',id,'on',props?.target);
  }
return (
  <div className="context-area-wrapper">
      <div className="context-area" onContextMenu={handleContextMenu}>
        <div data-page-id="page1"
        >Test Page 1</div>
        <div data-page-id="page2"
        >Test Page 2</div>
        <div data-page-id="page3"
        >Test Page 3</div>
      </div>
      <Menu id={MENU_ID}>
        <Item id="item1" onClick={handleItemClick}>Item 1</Item>
        <Item id="item2" onClick={handleItemClick}>Item 2</Item>
        <Item id="item3" onClick={handleItemClick}>Item 3</Item>
      </Menu>
  </div>
 )
}

This solution worked just fine, but I ran into a problem when trying to use my actual data instead of just test divs.

Replacing

 <div className="context-area" onContextMenu={handleContextMenu}>
  <div data-page-id="page1"
  >Test Page 1</div>
  <div data-page-id="page2"
  >Test Page 2</div>
  <div data-page-id="page3"
  >Test Page 3</div>
</div>

with

<div className="context-area" onContextMenu={handleContextMenu}>
{
  structure.map((page: StructuredPage) => {
    return (
      <StructuredShortcut data-page-id={page.pageId} {...page} key={page.pageId}/>
    )
  })
}
</div>

Does not seem to work (presumably because there are more subcomponents than just a single "div" for the click target to hit).

Any suggestions for how I could improve this?

willow folio
#

@hollow plinth I'm guessing that event.target is an element inside StructuredShortcut so you'd have to look up the tree to find the data-page-id prop

#

Could do something like:

const handleContextMenu = (event: MouseEvent) => {
    function findPageId(el: HTMLElement | null) {
      if(!el) return undefined;
      if(el.dataset.pageId) return el.dataset.pageId;
      return findPageId(el.parentElement);
    }
    const pageId = findPageId(event.target as HTMLElement); // as ignores the weird case where event.target is something other than an HTMLElement
    if(!pageId) throw new Error("Failed to find pageId");
    show(/*...*/)
}
#

... but also putting the onContextMenu on the wrapper element might be unnecessary

#

I'd first try putting a handler on each top-level item:

#
const handleContextMenu = (pageId: string) => (event: MouseEvent) => {
    show({
      event,
      props: {
        target: pageId,
      },
    });
}

<StructuredShortcut {...page} key={page.pageId} onContextMenu={handleContextMenu(page.pageId)} />
#

Unless something inside the <StructuredShortcut> is catching the same event and preventing it from bubbling, it should bubble up to the parent.

hollow plinth
#

This second solution seems to work well for me. Thanks!