-
-
Notifications
You must be signed in to change notification settings - Fork 10.7k
Description
The Link
component has some useful logic inside. I didn't see other ways to reuse it, but to render a <Link />
. It isn't very convenient when you use link/anchor components from another libraries which usually implies using as
props to replace underlying component. Sometimes it also gives you troubles with filtering additional props and sometimes requires hacks. I think it could be done without additional overhead and those forwardRefs
in the Link's code.
I've tried to do a couple of additional hooks, that translate this (with broken icon without additional work):
<Anchor label="MyApp" icon={Icons.Home} as={Link} to="/home" />
Into this (with working everyting):
<Anchor label="MyApp" icon={Icons.Home} {...useLink("/home")} />
The code is quite simple (also allows to get normalized href
and onClick
handler separately) and uses parts from the packages/react-router-dom/modules/Link.js
:
import {
resolveToLocation,
normalizeToLocation
} from "./utils/locationUtils.js";
const useHref = to => {
const history = useHistory();
const location = useLocation();
const resolvedLocation = resolveToLocation(to, location);
const normalizedLocation = normalizeToLocation(resolvedLocation, location);
return normalizedLocation ? history.createHref(normalizedLocation) : "";
};
const useClick = (to, replace = false) => {
const history = useHistory();
const location = useLocation();
const resolvedLocation = resolveToLocation(to, location);
const method = replace ? history.replace : history.push;
return useCallback(event => {
if (
!event.defaultPrevented && // onClick prevented default
event.button === 0 && // ignore everything but left clicks
!isModifiedEvent(event) // ignore clicks with modifier keys
) {
event.preventDefault();
method(resolvedLocation);
}
}, [resolvedLocation, method]);
};
const useLink = (to, replace = false) => {
return {
href: useHref(to),
onClick: useClick(to, replace),
};
};
You get the same href
with useHref
as Link
passes down and onClick
as combined logic from Link
and LinkAnchor
respectively with useClick
.
Finally, useLink
gives you and object to spread into a component whatever you use for displaying an anchor/link.
If this sounds interesting, I can make PR.