DEV Community

Tung Do
Tung Do

Posted on

How to use _activeLink in Chakra UI with Next.js

Next.JS is an excellent SSR framework, which many developers, including myself, love.

While I was working on a side project using Next.js and Chakra UI, I found out that Chakra has an official package @chakra-ui/next-js which support next/link (chakra with next.js link)

// app/page.tsx
'use client'
import { Link } from '@chakra-ui/next-js'

export default function Page() {
  return (
    <Link href='/about' color='blue.400' _hover={{ color: 'blue.500' }}>
      About
    </Link>
  )
}
Enter fullscreen mode Exit fullscreen mode

Note: if you want to use Link this way, add this option into next.config.js

  experimental: {
    esmExternals: false,
  }
Enter fullscreen mode Exit fullscreen mode

Github issue

At first, it looks really simple, and Chakra also provides some style props like _hover for link's hover style and _activeLink for a link's active style.
However, there is one issue: There aren't any native support for the active state of this Link component.

I know that there are a bunch of tutorials about manually creating an ActiveLink component in your project, even Next.js has an example of creating that component (check this out). Still, it would be really nice to have a native component, instead of having to manually create it for every new project. Something like this react-router's Navlink could be nice:

import { NavLink } from "react-router-dom";

<NavLink
  to="/messages"
  className={({ isActive, isPending }) =>
    isPending ? "pending" : isActive ? "active" : ""
  }
>
  Messages
</NavLink>;
Enter fullscreen mode Exit fullscreen mode

Nonetheless, we will still have to deal with it. So, let's-once again-create a NavLink component:

import {Link, LinkProps as ChakraLinkProps} from "@chakra-ui/next-js";
import {useColorModeValue} from "@chakra-ui/react";
import {useRouter} from "next/router";
import {LinkProps as NextLinkProps} from "next/link";

// Take note on how I implement these type, to be able to correctly pass the props
export default function NavLink ({ href, children, ...rest }: ChakraLinkProps & NextLinkProps) {
    const router = useRouter();
    const isActive = router.asPath === href; // Great, now we have the `active` state

    return (
        <Link
            px={2}
            py={1}
            rounded={'md'}
            _hover={{
                textDecoration: 'none',
                bg: useColorModeValue('gray.200', 'gray.700'),
            }}
            href={href}
            {...rest}
        >
            {children}
        </Link>
    )
};
Enter fullscreen mode Exit fullscreen mode

Now, normally, we will do some thing like

<Link className={isActive ? 'active-class' : ''} />
// active-class or styles.activeClass if you are using css module
Enter fullscreen mode Exit fullscreen mode

Or, we can notice this
How to active _activeLink style
then, update our NavLink component from above:

<Link
    className={isActive ? 'active-class' : ''}
    px={2}
    py={1}
    rounded={'md'}
    _hover={{
        textDecoration: 'none',
        bg: useColorModeValue('gray.200', 'gray.700'),
    }}
    href={href}
    // this line of code decide the active state of link, and apply the _activeLink style
    aria-current={isActive ? 'page' : undefined}
    {...rest}
>
    {children}
</Link>
Enter fullscreen mode Exit fullscreen mode

And finally, using it:


<NavLink 
    href="/"
    _activeLink={{
        textDecoration: 'none',
        bg: 'dark',
    }}
>
    Home
</NavLink>

<NavLink 
    href="/blogs"
    _activeLink={{
        textDecoration: 'none',
        bg: 'blue',
    }}
>
    Blogs
</NavLink>
Enter fullscreen mode Exit fullscreen mode

The source code for this blog is available on GitHub.

Top comments (2)

Collapse
 
codajoao profile image
João Paulo

Your tutorial has been helpful to me! Thank you :)

Collapse
 
tungdt90 profile image
Tung Do

Oh my!

I'm so glad that my post can provide some support for you.