How to use _activeLink in Chakra UI with Next.js
Tags: nextjs, chakraui, javascript
Published: 2023-03-14 08:59:26

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](https://chakra-ui.com/getting-started/nextjs-guide#chakra-ui-with-nextjs-link))

```tsx
// 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>
  )
}
```
Note: if you want to use `Link` this way, add this option into `next.config.js`
```js
  experimental: {
    esmExternals: false,
  }
```
[Github issue](https://github.com/chakra-ui/chakra-ui/issues/7363#issuecomment-1439466358)


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](https://github.com/vercel/next.js/tree/canary/examples/active-class-name)). 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:

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

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

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

```tsx
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>
    )
};
```

Now, normally, we will do some thing like
```tsx
<Link className={isActive ? 'active-class' : ''} />
// active-class or styles.activeClass if you are using css module
```
Or, we can notice this
![How to active _activeLink style](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a9jhm7uv28057w4i8xvi.png)
then, update our `NavLink` component from above:
```tsx
<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>
```

And finally, using it:
```tsx

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

<NavLink 
    href="/blogs"
    _activeLink={{
        textDecoration: 'none',
        bg: 'blue',
    }}
>
    Blogs
</NavLink>
```

The source code for this blog is [available on GitHub](https://github.com/tungdt-90/nextjs-chakra-ui-active-link).