[Feature]: `onNavigate` callback on `<Link />` and/or `useLinkClickHandler` that only triggers when following the link
What is the new or updated feature that you are suggesting?
It is already possible to attach an onClick handler to a <Link /> element, which triggers when the user clicks it. However, by default, this applies to all clicks, not just the clicks that trigger navigation.
In particular, a Ctrl+Click (on Windows) or Cmd+Click (on Mac) will open the linked-to target in a new tab; likewise, a right-click or middle-click don't trigger navigation. For reference, the existing logic looks like this:
(event: React.MouseEvent<E, MouseEvent>) => {
if (
event.button === 0 && // Ignore everything but left clicks
(!target || target === "_self") && // Let browser handle "target=_blank" etc.
!isModifiedEvent(event) // Ignore clicks with modifier keys
) {
event.preventDefault();
// If the URL hasn't changed, a regular <a> will do a replace instead of
// a push, so do the same here.
let replace =
!!replaceProp || createPath(location) === createPath(path);
navigate(to, { replace, state });
}
},
<Link /> should provide an onNavigate callback prop (possibly with a different name) that is called when the link is interacted with and is called only when the same logic for navigate applies.
Why should this feature be included?
It is entirely possible to emulate this "in userspace", by replicating the logic for checking whether the event is modified and which button is set and whether it opens in a new tab.
However, the developer must duplicate this logic, and doing so is potentially error-prone, as it's easy to make a mistake if you're not entirely familiar with how links are handled by the browser (for example, you could forget about one of the modifiers, or you could forget to check which mouse button was used, or you could forget about the case where an explicit target is set).
Since react-router-dom is already performing these checks, it should expose a callback so that a developer can re-use this logic without needing to duplicate code. The actual change would be only one or two lines plus any needed declarations.
The name onNavigate might be unclear; onNavigationClick or onBeforeNavigateClick or something similar might be clearer and more self-descriptive. Obviously this isn't a commonly-needed feature, so it's fine if its name is relatively long, as long as it's clear.
Also, remember that you can navigate a link by focusing it and pressing Enter. So a "click" is not required.
Also, remember that you can navigate a link by focusing it and pressing Enter. So a "click" is not required.
Yes, though at least in this case React handles this aspect for you, since it automatically triggers the onClick handler when you press enter/space on a button or anchor. Though, again, if you were to (incorrectly) rely on e.g. onMouseDown then you wouldn't get this behavior.
So that's another example of where the semantics are a bit complicated because there's many details that a developer might not know, and it would be more robust to lean on react-router's existing, well-tested implementation of the logic so that it works consistently.
I'm going to convert this to a discussion so it can go through our new Open Development process. Please upvote the new Proposal if you'd like to see this considered!