Integrating Material UI into a React NextJS app
Let’s breakdown how to add Material UI to a NextJS app to get you running with it in no time!
You can view the full change here if you’re impatient 😄, it’s part of a larger project for a react-portfolio-app.
Start by following the general installation guide here where we install Material UI, emotion/react, and emotion/styled for customized css.
yarn add @mui/material @emotion/react @emotion/styled
We can use Emotion styled components to define React components with styling attached to them. This makes our code more readable because everything is in a JSX format and the styling is contained in a reusable component.
Specific configuration changes for NextJS
There are three changes we need to make to the application
- Add App Router
- Create a theme
- Consume the theme in a ThemeProvider client-rendered file
We need to install specific dependencies for NextJS integration with Material UI, which involves using the App Router instead of Page Router.
yarn add @mui/material-nextjs @emotion/cache
1. Add App Router
Add AppRouterCacheProvider
to the root layout
// app/layout.tsx
import { AppRouterCacheProvider } from '@mui/material-nextjs/v13-appRouter';
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>
<AppRouterCacheProvider>
{children}
</AppRouterCacheProvider>
</body>
</html>
);
}
2. Create a Theme
Create a file theme.ts
and define the theme to be used by the ThemeProvider
as outlined in the doc.
// app/theme.ts
'use client';
import { Roboto } from 'next/font/google';
import { createTheme } from '@mui/material/styles';
const roboto = Roboto({
weight: ['300', '400', '500', '700'],
subsets: ['latin'],
display: 'swap',
});
const theme = createTheme({
typography: {
fontFamily: roboto.style.fontFamily,
},
});
export default theme;
3. Consume the theme in a ThemeProvider client-rendered file
Instead of adding the ThemeProvider
directly to the root layout.tsx
, you’ll need to create a separate file containing ThemeProvider
and call that in layout.tsx
. We do this because ThemeProvider
sets up a client-side context which cannot be rendered server-side, so we pull the code into its own client-rendered file and call it in layout.tsx
.
In this new file called StyledRoot.tsx
, we start the file with ‘use client’
to signify this is a client-side rendered file (read more here). Here’s what the file will look like:
// app/StyledRoot.tsx
'use client';
import { ThemeProvider } from '@mui/material/styles';
import theme from './theme';
export function StyledRoot({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<ThemeProvider theme={theme}>
{children}
</ThemeProvider>
);
}
Then we add it to layout.tsx
which will pass child components through to StyledRoot.tsx
// app/layout.tsx
import { AppRouterCacheProvider } from '@mui/material-nextjs/v13-appRouter';
import { StyledRoot } from './StyledRoot';
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>
<AppRouterCacheProvider>
<StyledRoot>{children}</StyledRoot>
</AppRouterCacheProvider>
</body>
</html>
);
}
And that’s it!
Now you have Material UI up and running with a NextJs app. The next step is to start adding components!
Start by perusing the component library — see what components support your design and look at the code examples for how to implement them!
Another great resource are the Material UI templates which use most of the Material UI components in real world examples. I find these examples to be the most useful — I took a special interest in the Blog template when building my portfolio app.
That’s all folks! Please let me know if you found this article helpful and if it’s missing any important details!