Make Material UI Use NextJS Links Internally by Default for Flawless Navigation

Tech

  • NextJS v14
  • Material UI v5

NextJS has its own Link component which is an extended HTML <a> element. It provides client-side navigation and prefetching. MUI provides Link component as well. Now you probably want to combine them together to get NextJS navigation benefits and the styling and theme from MUI.

Fortunately MUI offers a way to override the component MUI uses links for Link and Button directly in the theme. We need to create a forward ref to the NextJS Link component to which we'll pass all the props and then use our new component in the theme.

1import { createTheme } from '@mui/material/styles';
2import NextLink from 'next/link';
3import { forwardRef, LegacyRef } from 'react';
4
5const MUINextLink = forwardRef(function MUINextLink(props: any, ref: LegacyRef<HTMLAnchorElement>) {
6    return <NextLink ref={ref} {...props} />;
7})
8
9const mainTheme = createTheme({
10    components: {
11        MuiLink: {
12            defaultProps: {
13                component: MUINextLink
14            }
15        },
16        MuiButtonBase: {
17            defaultProps: {
18                LinkComponent: MUINextLink
19            }
20        }
21    },
22    // ...
23})

The LegacyRef<HTMLAnchorElement> type definition is required otherwise TypeScript complains - despite it being completely fine and the ref working as it should. Older solution for NextJS 13 and earlier is to wrap the MUI Link (without href) with NextJS Link (with href) and then use the passHref attribute.

1import NextLink from 'next/link'
2import { Link as MUILink } from '@mui/material';
3
4<NextLink href="/" passHref>
5    <MUILink variant="body2">Your Link</MUILink>
6</NextLink>
7