In this article, we will learn some additional necessary steps to be performed to integrate Material-UI with the Next.js project.
First Let’s start by creating a Next.js project.
Create Next.js project: Run the following command in the terminal
npx create-next-app gfg-next-mui
Project Structure: It will look like this.
Install Material-UI: To install the dependencies and save them in your package.json file, run:
npm install @mui/material @emotion/react @emotion/styled @emotion/server
Now follow the below steps:
Step 1: Create a custom file /pages/_document.js and add the following code to it.
import * as React from 'react' ;
import Document, { Html, Head, Main, NextScript } from 'next/document' ;
import createEmotionServer from '@emotion/server/create-instance' ;
import theme from '../src/theme' ;
import createEmotionCache from '../src/createEmotionCache' ;
export default class MyDocument extends Document {
render() {
return (
<Html lang= "en" >
<Head>
{ /* PWA primary color */ }
<meta name= "theme-color" content={theme.palette.primary.main} />
<link rel= "shortcut icon" href= "/static/favicon.ico" />
<link
rel= "stylesheet"
href=
"https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
{ /* Inject MUI styles first to match with the prepend: true configuration. */ }
{ this .props.emotionStyleTags}
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
} // `getInitialProps` belongs to `_document` (instead of `_app`), // it's compatible with static-site generation (SSG). MyDocument.getInitialProps = async (ctx) => { const originalRenderPage = ctx.renderPage;
// You can consider sharing the same emotion cache between
// all the SSR requests to speed up performance.
// However, be aware that it can have global side effects.
const cache = createEmotionCache();
const { extractCriticalToChunks } = createEmotionServer(cache);
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) =>
function EnhanceApp(props) {
return <App emotionCache={cache} {...props} />;
},
});
const initialProps = await Document.getInitialProps(ctx);
// This is important. It prevents emotion to render invalid HTML.
// See
const emotionStyles = extractCriticalToChunks(initialProps.html);
const emotionStyleTags = emotionStyles.styles.map((style) => (
<style
data-emotion={`${style.key} ${style.ids.join(' ')}`}
key={style.key}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: style.css }}
/>
));
return {
...initialProps,
emotionStyleTags,
};
}; |
Step 2: Create an src folder, add theme.js and createEmotionCache.js files as below
import { createTheme } from '@mui/material/styles' ;
import { red } from '@mui/material/colors' ;
// Create a theme instance. const theme = createTheme({ palette: {
primary: {
main: '#556cd6' ,
},
secondary: {
main: '#19857b' ,
},
error: {
main: red.A400,
},
},
}); export default theme;
|
import createCache from '@emotion/cache' ;
export default function createEmotionCache() {
return createCache({ key: 'css' , prepend: true });
} |
Step 3: Update the file /pages/_app.js with the below code
import * as React from 'react' ;
import PropTypes from 'prop-types' ;
import Head from 'next/head' ;
import { ThemeProvider } from '@mui/material/styles' ;
import CssBaseline from '@mui/material/CssBaseline' ;
import { CacheProvider } from '@emotion/react' ;
import theme from '../src/theme' ;
import createEmotionCache from '../src/createEmotionCache' ;
// Client-side cache shared for the whole session // of the user in the browser. const clientSideEmotionCache = createEmotionCache(); export default function MyApp(props) {
const { Component, emotionCache =
clientSideEmotionCache, pageProps } = props;
return (
<CacheProvider value={emotionCache}>
<Head>
<meta name= "viewport" content= "initial-scale=1, width=device-width" />
</Head>
<ThemeProvider theme={theme}>
{ /* CssBaseline kickstart an elegant,
consistent, and simple baseline to
build upon. */ }
<CssBaseline />
<Component {...pageProps} />
</ThemeProvider>
</CacheProvider>
);
} MyApp.propTypes = { Component: PropTypes.elementType.isRequired,
emotionCache: PropTypes.object,
pageProps: PropTypes.object.isRequired,
}; |
Step 4: Update the file /pages/index.js with the below code
import Head from "next/head" ;
import styles from "../styles/Home.module.css" ;
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<link rel= "icon" href= "/favicon.ico" />
</Head>
<main className={styles.main}>
<h1 className={styles.title}>
Next.js!</a> integrated with { " " }
</h1>
<p className={styles.description}>
Get started by editing{ " " }
<code className={styles.code}>
pages/index.js</code>
</p>
</main>
</div>
);
} |
Steps to run the application: To run the app, type the following command in the terminal.
npm run dev
Output: