Using the Material UI Link component with the Next.JS Link Component

Viewed 11730

I am using Material-UI with Next.js. I would like to use the Material-UI Link component so that I can access to the variant and other Material UI related API props. At the same time, I need to use the Next.js Link component for linking between pages.

I am wondering, how do I use the two of them together so that I can get the linking benefits of the Next.js Link component along with the styling benefits of the MaterialUI link component.

Ideally, I'd like to create my own Link component that combines the two of them into my single component so that I can use it anywhere I need to within my project.

Any ideas?

7 Answers

You can wrap the Material UI link with the Next.js one. This will provide the benefits of using both.

import NextLink from 'next/link'
import { Link as MUILink } from '@mui/material';

// ...

<NextLink href="/" passHref>
    <MUILink variant="body2">Your Link</MUILink>
</NextLink>

Link accepts a component prop that combines both properties. It works perfectly with react-router, might also work well with netxjs Link.

<Link component={NextjsLink}>Link Text</Link>

Here change the import name of the nextjs link.

Related Material-ui Documentation

I disagree with all the accepted answers. This is what I found to be the most succinct and clear.

<Button // MUI Button
  href="/employees"
  component="a"
  LinkComponent={Link} // NextJS Link
>
  Manage Employees
</Button>

This pattern works on most (all?) MUI components.

To avoid Ref warnings and some errors, I had to do this.

import NextLink from 'next/link';
import { Link as MuiLink } from '@mui/material';

const Link = forwardRef((props: any, ref:any)=>{
  const {href} = props;
  return <NextLink href={href} passHref >
          <MuiLink ref={ref} {...props}/>
          </NextLink>
})
Link.displayName = 'CustomLink';

This is how I used it.

<CardActionArea LinkComponent={Link} href={'/home'}>
...
</CardActionArea>

TypeScript version of the Next.js Link and Material UI Link/Button (v5) with forwardRef can be found at https://gist.github.com/kachar/028b6994eb6b160e2475c1bb03e33e6a

Adding some of the components here for brevity

import React, { forwardRef, Ref } from 'react'
import Link, { LinkProps } from 'next/link'
import { Button, ButtonProps } from '@mui/material'

type LinkRef = HTMLButtonElement
type NextLinkProps = Omit<ButtonProps, 'href'> &
  Pick<LinkProps, 'href' | 'as' | 'prefetch' | 'locale'>

const LinkButton = ({ href, as, prefetch, locale, ...props }: LinkProps, ref: Ref<LinkRef>) => (
  <Link href={href} as={as} prefetch={prefetch} locale={locale} passHref>
    <Button ref={ref} {...props} />
  </Link>
)

export default forwardRef<LinkRef, NextLinkProps>(LinkButton)
import React from "react";
import { Link as LinkMUI, LinkProps as LinkMUIProps } from "@mui/material";
import NextLink, { LinkProps as NextLinkProps } from "next/link";

export type LinkProps = Omit<LinkMUIProps, "href" | "classes"> &
  Pick<NextLinkProps, "href" | "as" | "prefetch">;

export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
  ({ href, as, prefetch, ...props }, ref) => (
    <NextLink href={href} as={as} prefetch={prefetch} passHref>
      <LinkMUI ref={ref} {...props} />
    </NextLink>
  )
);

The best anwser I found was this

We can create a custom component using Next Link and MUI Link

import NextLink from "next/link";
import MuiLink from "@mui/material/Link";
import MuiButton from "@mui/material/Button";

export default function Link({ type, href, children, ...props }) {
  if (type === "link" || !type) {
    return (
      <NextLink href={href} passHref>
        <MuiLink {...props}>{children}</MuiLink>
      </NextLink>
    );
  } else if (type === "button") {
    return (
      <NextLink href={href} passHref>
        <MuiButton {...props}>{children}</MuiButton>
      </NextLink>
    );
  }

And then, where you wanna use, you can use like this:

import Link from "../path/to/link";
// Later...
<Link type="button" href="/somewhere">Yay!</Link>

Is the best solution by far...

Credits: codingjlu

Had the same problem with the Button component from Material UI. It was not accepting component property because looks like it was not declared. This solved the issue (added component property to the Buton.d.ts): component?: Function;

Here the solution: Buton.d.ts file modified

and boom no error anymore:

Index file no error

Related