Last active
January 17, 2024 07:25
-
-
Save Phryxia/677bb0f4aeb14418e847d6946ba390ed to your computer and use it in GitHub Desktop.
React wrapper for vanilla anchor element considering `href` to internal pages
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { AnchorHTMLAttributes, MouseEvent as ReactMouseEvent, useCallback } from 'react' | |
| const InternalUrlRegexp = /^\.?\// | |
| const StartingDotRegexp = /^\./ | |
| export function Anchor({ | |
| children, | |
| href, | |
| onClick, | |
| ...rest | |
| }: AnchorHTMLAttributes<HTMLAnchorElement>) { | |
| const handleClick = useCallback( | |
| (e: ReactMouseEvent<HTMLAnchorElement, MouseEvent>) => { | |
| onClick?.(e) | |
| const isAbsoluteHost = href?.startsWith(location.origin) | |
| const isRelativeHost = href?.match(InternalUrlRegexp) | |
| if (!isAbsoluteHost && !isRelativeHost) return | |
| e.preventDefault() | |
| if (isAbsoluteHost) { | |
| history.pushState(null, '', href) | |
| } else { | |
| history.pushState(null, '', origin + href?.replace(StartingDotRegexp, '')) | |
| } | |
| }, | |
| [onClick], | |
| ) | |
| return ( | |
| <a onClick={handleClick} href={href} {...rest}> | |
| {children} | |
| </a> | |
| ) | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
When using react, it's verty tidious to disable default behavior of anchor element while preserving accessibilities. You may want to develop your own routing system while not using react-router kind of things.
If you're using next.js, DO NOT use this becasue
<Link>fromnext/linkwill does it for you. Also this may break next.js's internal routing invariants inside of the history objects.Behavior
hrefstarts with/or./, it push url whichhrefis appended, withnullhistory state.hrefstarts with currentorigin, it push givenhrefwithnullhistory state.Note
onClickis called before history is pushed.Usage