💅

Next.jsでstyled-componentsを使うときに最初に設定しておくこと【完全版】

2021/01/11に公開

Next.js×TypeScript で styled-components を使うときの設定【完全版】

今回は Next.js, TypeScript, styled-components の構成でアプリ開発を始める前の設定の紹介

特に以下の不整合を解消します

  • Next.js で styled-components を使うとスタイルがあたらない状態になることがある
  • Console で Prop `className` did not match. というエラーが出ている

最初にインストールするものたち

Next.js でプロジェクトを作成

インストールというかプロジェクトフォルダを作成します.

yarn create next-app ふぉるだのなまえ

で Next.js のセットアップが完了します.完了後はcd ふぉるだのなまえで移動しておきましょう.

TypeScript セットアップ

Next.js は親切でなので,pages/index.jspages/index.tsxなどとしてからyarn devすると

Please install typescript and @types/react by running:

        yarn add --dev typescript @types/react

If you are not trying to use TypeScript, please remove the tsconfig.json file from your package root (and any TypeScript files in your pages directory).

このように「TypeScript 入れてー」って言われます.

yarn add --dev typescript @types/react

として入れましょう.

styled-components をインストール

TypeScript に対応できるように型も一緒にインストールしておきます.

yarn add styled-components @types/styled-components

Next.js で styled-components を使うとスタイルがあたらない状態になることがあるを対処

スタイルが当たらない現象がおこるのは styled-components の公式に対処方法が書いてあるのでこの通りにします.

https://styled-components.com/docs/advanced#nextjs

pages/_document.tsxを以下のように書いて追加します.

import Document, { DocumentContext } from 'next/document';
import { ServerStyleSheet } from 'styled-components';

export default class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }
}

tsx で書く場合は,
static async getInitialProps(ctx: DocumentContext) {
のように型をつけてあげるようにしましょう.

renderPage()ってメソッドを使っていい感じにしてくれるみたい.

Console で Prop `className` did not match. というエラーが出ているを対処

フロント側の Console で,

Warning: Prop `className` did not match. Server: "sc-eCApnc dSSIyK" Client: "sc-bdnxRM hTEjgj"

のようなエラーが出ています.

styled-components は className を管理してスタイリングしており,この className がサーバーとフロントで一致してないよというエラーです.
Next.js の公式に書いてあるとおりに直してみます.
https://nextjs.org/docs/basic-features/built-in-css-support#css-in-js

インストール

yarn add babel-plugin-styled-components

.babelrc を作成

プロジェクトフォルダの直下に.babelrcを以下のように書き,追加します.

{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true }]]
}

これでエラーは消えているはずです.

これで,Next.js, TypeScript, styled-components でのアプリ開発を楽しめるかと思います!

Happy hacking!!

Discussion