davidtheclark / davidtheclark/react-aria-menubutton

React Router Link inside `MenuButton`

Open
#117 3 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
TypeScript
Stars
452
Forks
76
PR merge metrics
No merged PRs in 30d

Description

I am trying to create a menu whereby each item is a link. The reason I want a link rather than a button:

- accessibility, e.g. right click -> open in new tab
- semantics, links are important for SEO

I understand that `MenuButton` supports a `tag` prop, so you could do something like ``, however in this case we need to use React Router's `Link` component rather than the `a` element. This is because React Router's `Link` component has special behaviour, such as calling `history.pushState` when the link is clicked (as opposed to performing a full page navigation).

For that reason, I tried the following:

- nest a `Link` inside of a `MenuButton`
- implement `Wrapper`'s `onSelection` to run `history.push`, so it behaves the same as the link

Example: https://react-ts-bkz4fo.stackblitz.io/
Code: https://stackblitz.com/edit/react-ts-bkz4fo

One downside to this is we have to repeat the link in both `Wrapper`'s `onSelection` and `Link`. But more importantly, doing this means that on click, two events handlers would be called rather than one: `Link`'s `onClick` (which calls `history.push`) and `Wrapper`'s `onSelection`. This in turn means `history.push` is called twice, resulting in an extraneous history entry.

Screenshot 2020-02-05 at 13 16 21

If you select an item from the menu, you'll see that the history contains double entries.

To workaround this, my first thought was to remove the `Wrapper`'s `onSelection` and just use `Link`'s `onClick`, however this means the link would not be actioned when navigating the menu via the keyboard.

Another idea I had was to `preventDefault` inside the `Link`'s `onClick`. This fixes the issue of "two event handlers are called" whilst preserving the semantics/a11y of a link, except that `command + click` (shortcut to open in new tab) will not work.

[Reach UI’s `MenuButton`](https://reacttraining.com/reach-ui/menu-button) solves this problem by providing a `MenuLink` that works just like a `MenuItem` except you can pass a custom link component to use instead of `a`: https://reacttraining.com/reach-ui/menu-button/#menulink-as. Furthermore, there is no need to implement a selection handler on the menu wrapper. Perhaps this library could do something similar?

Related: https://github.com/davidtheclark/react-aria-menubutton/issues/85

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.