何も考えずにNext.jsでMaterial UIを使おうとすると以下のエラーが出ます。
Warning: Prop 'className' did not match. Server ...
Material UIではSSRへの対応方法が準備されており、以下がそのサンプルです。
material-ui/examples/ssr at master · mui-org/material-ui · GitHub
上記のサンプルコードを初見で見て思ったのが、どこがポイントなのよ〜ってこと。
余計なコードがいろいろはいってて、どこがポイントなのか初心者にはわかりにくいです。
色々検証してわかったのは、以下のコードを追加すれば直るってこと。
_app.tsx: useEffectのところのみ必要。
import React from 'react'; export default function MyApp({ Component, pageProps }: AppProps) { React.useEffect(() => { // Remove the server-side injected CSS. const jssStyles = document.querySelector('#jss-server-side'); if (jssStyles) { jssStyles.parentElement!.removeChild(jssStyles); } }, []); .... return <Component {...pageProps} />; }
_document.tsx
ServerStyleSheetsをインポートする箇所と、
MyDocument.getInitialPropsを入れればOK
import { ServerStyleSheets } from '@material-ui/core/styles'; ... ... // `getInitialProps` belongs to `_document` (instead of `_app`), // it's compatible with server-side generation (SSG). MyDocument.getInitialProps = async (ctx) => { // Resolution order // // On the server: // 1. app.getInitialProps // 2. page.getInitialProps // 3. document.getInitialProps // 4. app.render // 5. page.render // 6. document.render // // On the server with error: // 1. document.getInitialProps // 2. app.render // 3. page.render // 4. document.render // // On the client // 1. app.getInitialProps // 2. page.getInitialProps // 3. app.render // 4. page.render // Render app and page and get the context of the page with collected side effects. const sheets = new ServerStyleSheets(); const originalRenderPage = ctx.renderPage; ctx.renderPage = () => originalRenderPage({ enhanceApp: (App) => (props) => sheets.collect(<App {...props} />), }); const initialProps = await Document.getInitialProps(ctx); return { ...initialProps, // Styles fragment is rendered after the app and page rendering finish. styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()], }; };
ただ自分の場合、next.config.jsでreactStrictMode: trueをしてたためエラーがで出続けていました。これがわかるまでに結構大変でした。
潜在的な問題点を洗い出すためにtureにしたほうが良いようなのですが
Material UIと一緒に使う場合は、無効にしたほうが良さそう。
Next.js 4年目の知見:SSRはもう古い、VercelにAPIサーバを置くな - Qiita
Material UI v5では直ってるっぽいので、もうちょっとreactStricModeを使うのは待つほうが良いかも...
[styles] Strict Mode support · Issue #18018 · mui-org/material-ui · GitHub
[参考]
Material-UIでNext.jsのポイントを紹介する|fumi|note
フロントエンド初学者がNext.js + Typescript + FireStore + Material-UI + SSGでサイト作るまでのメモ
【Next.js】Material-UI導入時に[Warning: Prop `className` did not match. ]が発生した場合の対処法 - Qiita
Server Rendering - Material-UI