Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save revisualize/3c6bf297487dfa3ce38c2872735b6b5d to your computer and use it in GitHub Desktop.
Save revisualize/3c6bf297487dfa3ce38c2872735b6b5d to your computer and use it in GitHub Desktop.
useLinkHandler.js
// Turn all HTML <a> elements into client-side router links, no special framework-specific <Link> component necessary!
function useLinkHandler() {
function handleClick(e) {
const link = e.target.closest('a');
const isAnchorLink = link && link.href && link.href.startsWith('#');
// Check if the clicked element is a valid <a> tag and meets the navigation criteria
if (
link &&
link instanceof HTMLAnchorElement &&
link.href &&
(!link.target || link.target === '_self' || link.target === '_blank') &&
(!link.origin || link.origin === location.origin) &&
!link.hasAttribute('download') &&
((e.button === 0 && !e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey) ||
(e.key === 'Enter' && !e.shiftKey)) &&
!e.defaultPrevented
) {
e.preventDefault();
// Handle the navigation based on whether it's an anchor link or a regular link
if (isAnchorLink) {
handleAnchorLink(link);
} else {
handleNavigation(link.href);
}
}
}
// Debounce the click event handler to improve performance
function debounce(func, delay) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), delay);
};
}
// Handle navigation for anchor links within the same page
function handleAnchorLink(link) {
const targetId = link.getAttribute('href').slice(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
smoothScrollTo(targetElement);
}
}
// Handle navigation for regular links
function handleNavigation(href) {
window.location.href = href;
}
// Smooth scroll to an element on the page
function smoothScrollTo(element) {
// Implement smooth scrolling logic here
// Example: window.scrollTo({ top: element.offsetTop, behavior: 'smooth' });
}
useEffect(() => {
const debouncedHandleClick = debounce(handleClick, 300);
// Attach the click and keydown event listeners to the document
document.addEventListener('click', debouncedHandleClick, { capture: true });
document.addEventListener('keydown', debouncedHandleClick, { capture: true });
// Cleanup by removing the event listeners
return () => {
document.removeEventListener('click', debouncedHandleClick, { capture: true });
document.removeEventListener('keydown', debouncedHandleClick, { capture: true });
};
}, []);
return null;
}
export default useLinkHandler;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment