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>
)
}
Note: if you want to use Link
this way, add this option into next.config.js
experimental: {
esmExternals: false,
}
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>;
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>
)
};
Now, normally, we will do some thing like
<Link className={isActive ? 'active-class' : ''} />
// active-class or styles.activeClass if you are using css module
Or, we can notice this
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>
And finally, using it:
<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.
Top comments (2)
Your tutorial has been helpful to me! Thank you :)
Oh my!
I'm so glad that my post can provide some support for you.