Next.js Chakra UI Link Component

Link component for both dynamic and external links in Next.js projects using Chakra UI.

Next.js Chakra UI Link Component
import type { PropsWithChildren } from 'react'
import type { LinkProps as NextLinkProps } from 'next/link'

import NextLink from 'next/link'
import {
  Button as ChakraButton,
  ButtonProps as ChakraButtonProps,
  BreadcrumbLink as ChakraBreadcrumbLink,
  BreadcrumbLinkProps as ChakraBreadcrumbLinkProps,
  Link as ChakraLink,
  LinkProps as ChakraLinkProps,
} from '@chakra-ui/react'

type NextLinkAs = NextLinkProps['as']

type LinkProps<T> =
  | PropsWithChildren<NextLinkProps & Omit<T, 'as'>>
  | PropsWithChildren<Omit<NextLinkProps, 'as'> & T>

type ChakraLinkAs = ChakraLinkProps['as']

//  Has to be a new component because both chakra and next share the `as` keyword
export const Link = ({
  href,
  as,
  replace,
  scroll,
  shallow,
  prefetch,
  locale,
  isExternal,
  children,
  ...chakraProps
}: LinkProps<ChakraLinkProps>) => {
  return isExternal ? (
    <ChakraLink href={href} as={as as ChakraLinkAs} isExternal {...chakraProps}>
      {children}
    </ChakraLink>
  ) : (
    <NextLink
      passHref={true}
      href={href}
      as={as as NextLinkAs}
      replace={replace}
      scroll={scroll}
      shallow={shallow}
      prefetch={prefetch}
      locale={locale}
    >
      <ChakraLink {...chakraProps}>{children}</ChakraLink>
    </NextLink>
  )
}

export const ButtonLink = ({
  href,
  as,
  replace,
  scroll,
  shallow,
  prefetch,
  locale,
  children,
  ...chakraProps
}: LinkProps<ChakraButtonProps>) => {
  return (
    <NextLink
      passHref={true}
      href={href}
      as={as as NextLinkAs}
      replace={replace}
      scroll={scroll}
      shallow={shallow}
      prefetch={prefetch}
      locale={locale}
    >
      <ChakraButton as='a' {...chakraProps}>
        {children}
      </ChakraButton>
    </NextLink>
  )
}

export const BreadcrumbLink = ({
  href,
  as,
  replace,
  scroll,
  shallow,
  prefetch,
  locale,
  children,
  ...chakraProps
}: LinkProps<ChakraBreadcrumbLinkProps>) => {
  return (
    <NextLink
      passHref={true}
      href={href}
      as={as as NextLinkAs}
      replace={replace}
      scroll={scroll}
      shallow={shallow}
      prefetch={prefetch}
      locale={locale}
    >
      <ChakraBreadcrumbLink {...chakraProps}>{children}</ChakraBreadcrumbLink>
    </NextLink>
  )
}

Usage

This component can replace any link components in a Next.js project built with Chakra UI. It can be used as a replacement for the <Link> component in Next.js. for next/link. It can also be used as an external link by providing the isExternal prop.

Last updated April 01, 2022