How to use Nextjs Link with Chakra UI
Photo By Edge2Edge Media
One of the frequently asked questions on chakra ui library discussions is, How do I use nextjs link with chakra ui button or chakra link? In this post let us explore some common patterns to use nextjs link with chakra.
NextJS provides a Link component out of the box, that can be used for Client-side transitions between different routes. This Link
component is exported from next/link
package.
What is so special about this component is, it prefetches the linked route by default to provide rapid fast 🚀 page transitions. Until the Link becomes visible to the user, it won't prefetch the route, and once the Link is visible the prefetch is done in the background.
So, to use this component with our design system, we can create a custom component wrapper and make it reusable across the application. Let's see how to do that next.
🚨 From next v13 update, Link component behavior has been updated. Please check the last section of this post for workaround. In short, you would need to pass
legacyBehavior
prop to make the following tricks work with Chakra UI.
Create Chakra Button with Next Link#
Surround chakra Button
with next's Link
and provide a passHref
prop so that it forwards href to the rendered anchor tag for proper semantics and SEO.
1import Link from "next/link";2import { Button } from "@chakra-ui/react";34function ChakraNextLinkButton({ href, children, ...props }) {5 return (6 <Link href={href} passHref>7 <Button as="a" {...props}>8 {children}9 </Button>10 </Link>11 );12}1314function IndexPage() {15 return (16 <ChakraNextLinkButton href="/about" colorScheme="facebook">17 About18 </ChakraNextLinkButton>19 );20}
Notice the as
prop in chakra button on line number 7. We are rendering anchor tag instead of button on DOM and applying chakra button styles to it! You can pass all the chakra button props to the component ChakraNextLinkButton
like onClick, padding, margin etc.
With this approach, we are following proper web semantics.
We can change the variant
prop to 'link'
to the same component to render the link styles.
1<ChakraNextLinkButton href="/about" variant="link">2 About3</ChakraNextLinkButton>
At the same time, if you want to have control over next's Link
via props, you would need to separate the props in the custom component and pass it appropriately like below
1import Link from "next/link";2import { Button } from "@chakra-ui/react";34function ChakraNextLinkButton({ href, children, prefetch = true, ...props }) {5 return (6 <Link href={href} passHref prefetch={prefetch}>7 <Button as="a" {...props}>8 {children}9 </Button>10 </Link>11 );12}1314function IndexPage() {15 return (16 <ChakraNextLinkButton17 href="/about"18 colorScheme="facebook"19 prefetch={false}>20 About without prefetch21 </ChakraNextLinkButton>22 );23}
See more about Next's Link props in next's documentation about Link component
Create Chakra Link with Next Link#
If we want to use Chakra's Link with Next's Link, we can do that easily by this method.
1import Link from "next/link";2import { Link as ChakraLink } from "@chakra-ui/react";34function ChakraNextLink({ href, children, ...props }) {5 return (6 <Link href={href} passHref>7 <ChakraLink {...props}>{children}</ChakraLink>8 </Link>9 );10}1112function IndexPage() {13 return (14 <ChakraNextLink href="https://bharathikannan.com" isExternal color="red">15 Visit my homepage16 </ChakraNextLink>17 )18}
Notice that we can pass isExternal
prop to the custom component, and that would forward the prop to Chakra's Link component to add the target="_blank"
and rel="noopener noreferrer"
attributes to rendered HTML automatically.
Usage with Typescript#
If you are using next js with typescript and if you want to make use of typescript intellisense, code completion and static type checking for our custom chakra components, you can create a new prop type by merging Chakra's Props and Next's Props and provide it to our component like below
1import Link, { LinkProps } from "next/link";2import {3 Button,4 ButtonProps,5} from "@chakra-ui/react";67type ChakraAndNextProps = ButtonProps & LinkProps;89function ChakraNextLinkButton({10 href,11 children,12 prefetch = true,13 ...props14}: ChakraAndNextProps) {15 return (16 <Link href={href} passHref prefetch={prefetch}>17 <Button as="a" {...props}>18 {children}19 </Button>20 </Link>21 );22}2324function IndexPage() {25 return (26 <ChakraNextLinkButton href="/about" colorScheme="facebook">27 About28 </ChakraNextLinkButton>29 );30}
Wow! Now we got code completion with static props checking!
And for the Chakra Link,
1import Link, { LinkProps } from "next/link";2import {3 Link as ChakraLink,4 LinkProps as ChakraLinkProps,5} from "@chakra-ui/react";67type ChakraLinkAndNextProps = ChakraLinkProps & LinkProps;89function ChakraNextLink({ href, children, ...props }: ChakraLinkAndNextProps) {10 return (11 <Link href={href} passHref>12 <ChakraLink {...props}>{children}</ChakraLink>13 </Link>14 );15}161718function IndexPage() {19 return (20 <ChakraNextLink href="https://bharathikannan.com" isExternal color="red">21 Visit my homepage22 </ChakraNextLink>23 );24}
Great! Now we won't be missing Chakra's prop intellisense!
Note: In the above examples, you are responsible for separating chakra props and next props and passing it to the corresponding components!
Bonus Tip#
You can shorten the prop spreading on components without mentioning children
1// BEFORE2function ChakraNextLinkButton({ href, children, prefetch = true, ...props }) {3 return (4 <Link href={href} passHref prefetch={prefetch}>5 <Button as="a" {...props}>6 {children}7 </Button>8 </Link>9 );10}1112// AFTER13function ChakraNextLinkButton({ href, prefetch = true, ...props }) {14 return (15 <Link href={href} passHref prefetch={prefetch}>16 <Button as="a" {...props} />17 </Link>18 );19}
Next 13 Update#
In the new version of next v13, Link component behaviour has been updated, now it doesn't allow the child to be a
tag. In order to make the above tricks work, you would need to pass additional prop legacyBehavior
to the Link component.
1import Link from "next/link";2import { Button } from "@chakra-ui/react";34function ChakraNextLinkButton({ href, children, ...props }) {5 return (6 <Link href={href} passHref legacyBehavior>7 <Button as="a" {...props}>8 {children}9 </Button>10 </Link>11 );12}1314function IndexPage() {15 return (16 <ChakraNextLinkButton href="/about" colorScheme="facebook">17 About18 </ChakraNextLinkButton>19 );20}
At the time of writing this post, Chakra has just included their own next integration for Link component to support Next v13 updates. View their documentatiom on using the same: Chakra UI with Next.js Link. To note this new component integration has some open issues, so please read carefully before using it. View the issue ESM Import Error in chakra next link
Sandbox Links#
Here is the sandbox link for all the above examples to see it live ✅
- Javascript Sandbox with Chakra next Link Components
- Typescript Sandbox with Chakra next Link Components
Do you think anything else to be added? Did you notice any issues in the post? Let me know at my Twitter handle, or please feel free to submit a PR to edit this post! There should be an Edit this Post link below 😀
References
Published:September 4, 2021
Updated:June 10, 2024