🎨

Next.js12のLayoutsを使ってMUIのカスタムテーマをうまく読み込めないときの対処法

2023/01/30に公開

困ったこと:独自のテーマを使いたいのにデフォルトのテーマが表示される

Next.jsの公式ドキュメントを参考にして、複数ページに共通するレイアウトを切り出そうと実装したら、MUIで作成したカスタムテーマが適用されず、デフォルトのテーマが反映されてしまいました。

_app.tsx
import { ThemeDefinition } from 'placeOfThemeDefinition'

export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
  getLayout?: (page: ReactElement) => ReactNode
}

type AppPropsWithLayout = AppProps & {
  Component: NextPageWithLayout
}

export default function App({ Component, pageProps }: AppPropsWithLayout) {
  const getLayout = Component.getLayout ?? ((page) => page)
  return getLayout(
    <ThemeProvider theme={ThemeDefinition}> {/* MUIのカスタムテーマを使いたい*/}
      <CssBaseline></CssBaseline>
      <Component {...pageProps} />
    </ThemeProvider>
  )
}

上記コードの<ThemeProvider theme={ThemeDefinition}>のところでMUIのテーマを読み込んでいるのですが、うまく適用されませんでした。

解決策

getLayoutをテーマプロバイダの中に入れることで、無事にカスタムテーマが適用されました!

_app.tsx
// 中略

export default function App({ Component, pageProps }: AppPropsWithLayout) {
  const getLayout = Component.getLayout ?? ((page) => page)
- return getLayout(
+ return (
    <ThemeProvider theme={ThemeDefinition}> {/* MUIのカスタムテーマを使いたい*/}
      <CssBaseline></CssBaseline>
-     <Component {...pageProps} />
+     {getLayout(<Component {...pageProps} />)}
    </ThemeProvider>
  )
}

修正前のコードだと、テーマを適用している範囲の外でレイアウトを読み込んでしまっています。テーマを読み込む前にレイアウトを取得しているのですから、レイアウトが参照するテーマはデフォルトのテーマになるよね…ということでした。(気づけなかったのが悔しい。。)


なお、解決にあたって以下のページを参考にしました。
自分だけのニッチな問題かと思ったら、同様に困っている人はいるんだなと改めて。世界is広し。

参考:
https://stackoverflow.com/questions/69078144/next-js-context-provider-wrapping-app-component-with-page-specific-layout-compon
https://stackoverflow.com/questions/72933953/why-is-the-mui-theme-breaking-with-nextjs-layout

Discussion