nextjs에서 mui(material-ui)를 적용하는 방법에 대해 알아보겠습니다. 이 이후에는 다음은 styled-components와 mui를 동시에 사용하는 방법 (opens new window), 마지막에는 글로벌 style를 이용하여 다크모드 만드는 방법까지 알아보도록 하겠습니다.
타입스크립트 기반 예제로 이루어져있습니다.
npx create-next-app my-app
cd my-app
yarn add @emotion/react @emotion/styled @mui/icons-material @mui/material @mui/styles
#_document.tsx
import React from "react";
import Document, { Html, Head, Main, NextScript } from "next/document";
import { ServerStyleSheets } from "@mui/styles";
export default class MyDocument extends Document {
render() {
return (
<Html>
<body>
<Head></Head>
<Main />
<NextScript />
</body>
</Html>
);
}
}
MyDocument.getInitialProps = async ctx => {
const materialSheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props => materialSheets.collect(<App {...props} />)
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: <>{initialProps.styles}</>
};
};
// _app.tsx
import type { AppProps } from "next/app";
import CssBaseline from "@mui/material/CssBaseline";
const App = (props: AppProps) => {
const { Component, pageProps } = props;
return (
<>
<CssBaseline />
<Component {...pageProps} />
</>
);
};
export default App;
여기 까지 기본적인 세팅이 모두 완료되었습니다. 이제 컴포넌트 내부에서 mui를 사용할 수 있습니다.
import type { NextPage } from "next";
import Button from "@mui/material/Button";
const Home: NextPage = () => {
return (
<div>
<Button variant="contained">Contained</Button>
<Button variant="outlined">Outlined</Button>
</div>
);
};
export default Home;
import React from "react";
import Document, { Html, Head, Main, NextScript } from "next/document";
import { ServerStyleSheet } from "styled-components";
import { ServerStyleSheets } from "@mui/styles";
export default class MyDocument extends Document {
render() {
return (
<Html>
<Main />
<NextScript />
</Html>
);
}
}
MyDocument.getInitialProps = async ctx => {
const sheet = new ServerStyleSheet();
const materialSheets = new ServerStyleSheets();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props =>
sheet.collectStyles(materialSheets.collect(<App {...props} />))
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
};
} finally {
sheet.seal();
}
};