LoginSignup
10
4

More than 1 year has passed since last update.

Material-uiがv5へアップデートされたので、Next.jsで対応する。

Last updated at Posted at 2021-10-02

皆さんこんにちは。

Material-uiがv5へ大型なアップデートされましたね。

コンポーネント自体はCSSの扱いが変更されたくらいで大きな変更などはありませんが、パッケージ名が変わったので大きなプロジェクトで採用していると対応するのにかなり時間が掛かりそう。。。

また、CSSの扱い方がemotionstyled-componentsに合わせたらしいのでNext.jsやGatsby.jsなどのReactのフレームワークを利用している方はdocument、appファイルにいくつかの変更が加わります。

そこで、今回は、早速v5を体験したい方やv5のバージョンに対応したいという方に向けた記事となります。

コンポーネントの扱い方などは既に記事を出されている方も多いのですが、Next.jsでv5に対応する記事は少なかったため皆さんの助けになればなと思います。

注意事項

先程も申し上げたとおり、v5になってemotionとstyled-componentsが使用されるようになりました。

私自身、これらのCSSライブラリに触れたことがないため、今回はemotionで対応するだけの記事となりますのでご了承下さい。

時間があるときにstyled-componentsでの対応も追加していきます。

それでは早速説明していきます。

パッケージのインストール

// npm
npm i @mui/material @emotion/cache @emotion/react @emotion/server @emotion/styled

// yarn
yarn add @mui/material @emotion/cache @emotion/react @emotion/server @emotion/styled

emotionのキャッシュ(?)用のファイルを作成

stylesディレクトリにemotionのキャッシュ用のファイルを作成。

touch styles/createEmotionCache.ts
styles/createEmotionCache.ts
import createCache from '@emotion/cache';

export default function createEmotionCache() {
  return createCache({ key: 'css' });
}

_app.tsx

任意の場所に以下のプロバイダーを設置して下さい。

_app.tsx
import { CacheProvider } from '@emotion/react';
import createEmotionCache from '@/styles/createEmotionCache';

const clientSideEmotionCache = createEmotionCache();

const Appr: React.FC = ({ children }) => {
  return (
    <CacheProvider value={clientSideEmotionCache}>
      // 省略
    </CacheProvider>
  );
};

export default App;

_document.tsx

以下をコピペ

_document.tsx
import { Children, ReactElement } from 'react';
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionCache from '../styles/createEmotionCache';
import createEmotionServer from '@emotion/server/create-instance';

class MyDocument extends Document {
  render(): JSX.Element {
    return (
      <Html lang="ja">
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

MyDocument.getInitialProps = async (ctx) => {
  const originalRenderPage = ctx.renderPage;

  const cache = createEmotionCache();
  const { extractCriticalToChunks } = createEmotionServer(cache);

  ctx.renderPage = () =>
    originalRenderPage({
      enhanceApp: (App) =>
        function AppEmotionCache(props): ReactElement {
          return <App {...props} />;
        },
    });

  const initialProps = await Document.getInitialProps(ctx);

  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,
    // Styles fragment is rendered after the app and page rendering finish.
    styles: [...Children.toArray(initialProps.styles), ...emotionStyleTags],
  };
};

一応これでMateriuiのv5を使用することが出来ます。

若干付け焼き刃的な感じがしますが、そこは見逃していただけると幸いです。

もしかしたら、うまく動作しない場合もあるかもしれないのでコメントにて気軽にご質問下さい。

時間がるときにstyled-componentsの対応もします。

以上、「Material-uiがv5へアップデートされたので、Next.jsで対応する。」でした。

Thank you for reading

参考記事

https://www.ansonlowzf.com/create-a-website-with-material-ui-v5-nextjs/

10
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
4