Skip to main content

Conditional Link

Component that can differentiate between internal link or new tab link

––– views

Usage

This component will detect your href props, if it starts with https://, it will direct you to another tab. If it starts with / it will use Next.js / React Router Link Component.

Next.js Code:

// components/UnstyledLink.tsx import clsx from 'clsx'; import Link, { LinkProps } from 'next/link'; export type UnstyledLinkProps = { href: string; children: React.ReactNode; openNewTab?: boolean; className?: string; } & React.ComponentPropsWithoutRef<'a'> & LinkProps; export default function UnstyledLink({ children, href, openNewTab, className, ...rest }: UnstyledLinkProps) { const isNewTab = openNewTab !== undefined ? openNewTab : href && !href.startsWith('/') && !href.startsWith('#'); if (!isNewTab) { return ( <Link href={href}> <a {...rest} className={className}> {children} </a> </Link> ); } return ( <a target='_blank' rel='noopener noreferrer' href={href} {...rest} className={clsx(className, 'cursor-newtab')} > {children} </a> ); }
tsx

Create React App Code:

For Create React App with React Router, we need to use Link component from react router

// components/UnstyledLink.jsx import { Link } from 'react-router-dom'; export default function UnstyledLink({ href, className = '', openNewTab, children, ...rest }) { const isInternalLink = href && (href.startsWith('/') || href.startsWith('#')); // If is internal link, and no override specified if (isInternalLink && openNewTab === undefined) { return ( <Link to={href} className={className}> {children} </Link> ); } // If no override then _blank // if there is override then use the boolean return ( <a href={href} className={className} target={openNewTab === undefined || openNewTab ? '_blank' : undefined} rel='noopener noreferrer' {...rest} > {children} </a> ); }
jsx

Custom Style

To add some classes, I usually make another component such as buttons, hover links, etc.

import UnstyledLink from './UnstyledLink'; export default function CustomLink({ className = '', ...rest }) { return ( <UnstyledLink {...rest} className={`inline-flex items-center font-bold hover:text-primary-400 ${className}`} /> ); }
jsx