Reactでstyled-componentsを使う方法

2019-06-16

React(リアクト)でstyled-componentsを使う方法について見てみましょう。

概要

会社でReact(リアクト)で新しいプロジェクトをするこのになりました。それで久しぶりにReact(リアクト)を最初から設定するチャンスが出ってその内容をまとめることにしました。このブログポストではReact(リアクト)でstyled-componentsを使う方法について調べるし、React(リアクト)プロジェクトでstyled-componentsを使って見ます。

このブログで扱うソースコードはギットハブ(Github)に公開されております。

今回のブログポストで使ったソースコードは以前のブログを参考して作りました。

プロジェクト準備

このブログポストで使うReact(リアクト)プロジェクトはWebpack(ウェブパック)とTypescript(タイプスクリプト)が適用されたプロジェクトをベースにしています。詳しく内容は以前のブログポストを確認してください。

以前のブログポストを使ってプロジェクトを生成すると下記のような構造が出来上がります。私たちはreact_typescriptと言う名前ではなくreact_styled-componentsと言う名前でプロジェクトを生成しました。

|-- src
|   |-- index.html
|   |-- index.tsx
|-- .babelrc
|-- package.json
|-- webpack.config.js

インストール

下記のコマンドでReact(リアクト)でstyled-componentsを使うため必要なライブラリをインストールします。

npm install --save-dev styled-components @types/styled-components babel-plugin-styled-components cross-env
  • styled-components: styled-componentsを使います。
  • @types/styled-components: styled-componentsを使ってTypescript(タイプスクリプト)を使うためのライブラリ。
  • babel-plugin-styled-components: styled-componentsのclass名を分かりやすくしてくれるライブラリ。
  • cross-env: MacとWindowsで同じコマンドで環境変数を設定するためのライブラリ。

package.json修正

下記のようにpackage.jsonのスクリプト部分を修正します。

"scripts": {
  "start": "cross-env NODE_ENV=development webpack-dev-server --open",
  "prebuild": "rimraf dist",
  "build": "cross-env NODE_ENV=production webpack --progress"
},

以前のWebpack(Webpack)のモードを設定するため--mode development--mode productionを使いましたが、この部分を環境変数で設定するように修正しました。

Webpack修正

下記のようにwebpack.config.jsファイルを修正します。

...
module.exports = {
  mode: process.env.NODE_ENV,
  ...
};
...

以前はコマンドでモードを設定しましたが、環境変数で設定するためmodeを追加しました。

babel設定

下記のように.babelrcファイルを修正します。

{
  "presets": [
    ...
  ],
  "env": {
    "development": {
      "plugins": ["babel-plugin-styled-components"]
    }
  }
}

環境変数がdevelopmentの場合、class名を分かりやすくさせるためbabel-plugin-styled-componentsを設定しました。環境変数がproductionの場合class名がhash化されて人が認識づらくさせます。

[環境変数がdevelopmentの場合]

Reactでstyled-componentsを使う - 環境変数がdevelopmentの場合、class名

[環境変数がproductionの場合]

Reactでstyled-componentsを使う - 環境変数がproductionの場合、class名

styled-componentsスタイルコーディング

React(リアクト)でstyled-componentsを使うため./src/index.tsxを下記のように修正します。

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Styled from 'styled-components';

const Title = Styled.h1`
  color: red;
`;
interface Props {}

const App = ({  }: Props) => {
  return <Title>Hello World!</Title>;
};

ReactDOM.render(<App />, document.getElementById('app'));

確認

下記のコマンドで私たちが生成して設定した内容がうまく動いてるか確認します。

npm start

そしてブラウザを開いてhttp://localhost:8080/に移動するとHello World!が見えることが確認できます。package.jsonのスクリプトである"start": "webpack-dev-server --mode development","start": "webpack-dev-server --mode development --open",ように--openのオプションを追加するとnpm startでWebpack(ウェブパック)の開発サーバーを実行すると自動的ブラウザが立ち上がってhttp://localhost:8080/に移動します。

実行された開発サーバーをストップして、下記のコマンドでビルドしてみましょう。

npm run build

問題なく実行されたら./dist/フォルダが生成されてその下にindex.html/js/app.jsが生成されることが確認できます。また、index.htmlを開いてみたら私たちが作ったindex.htmlと違って<script type="text/javascript" src="/js/app.js"></script>が追加されたことが確認できます。

エラー対応

React(リアクト)プロジェクトを確認するためnpm startを実行する時は問題ありませんでしたが、npm run buildを使ってビルドする時下記のエラーが出ました。

ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/globals.d.ts
ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/globals.d.ts(36,15):
TS2300: Duplicate identifier 'FormData'.

ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/globals.d.ts
ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/globals.d.ts(81,5):
TS2717: Subsequent property declarations must have the same type.  Property 'body' must be of type 'BodyInit', but here has type 'string | ArrayBuffer | DataView | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | Blob | FormData'.

ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/globals.d.ts
ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/globals.d.ts(107,14):
TS2300: Duplicate identifier 'RequestInfo'.

ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/globals.d.ts
ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/globals.d.ts(126,13):
TS2403: Subsequent variable declarations must have the same type.  Variable 'Response' must be of type '{ new (body?: BodyInit, init?: ResponseInit): Response; prototype: Response; error(): Response; redirect(url: string, status?: number): Response; }', but here has type '{ new (body?: string | ArrayBuffer | DataView | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | Blob | FormData, init?: ResponseInit): Response; prototype: Response; error: () => Response; redirect: (url: string, status?: number) => Res...'.

ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/globals.d.ts
ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/globals.d.ts(249,14):
TS2300: Duplicate identifier 'XMLHttpRequestResponseType'.

ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/index.d.ts
ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/index.d.ts(9418,18):
TS2717: Subsequent property declarations must have the same type.  Property 'geolocation' must be of type 'Geolocation', but here has type 'GeolocationStatic'.

ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/index.d.ts
ERROR in /git_repository/react_styled-components/node_modules/@types/react-native/index.d.ts(9421,11):
TS2451: Cannot redeclare block-scoped variable 'navigator'.

ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts
ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts(5353,11):
TS2300: Duplicate identifier 'FormData'.

ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts
ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts(5363,13):
TS2300: Duplicate identifier 'FormData'.

ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts
ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts(17123,11):
TS2320: Interface 'Window' cannot simultaneously extend types 'GlobalFetch' and 'WindowOrWorkerGlobalScope'.
  Named property 'fetch' of types 'GlobalFetch' and 'WindowOrWorkerGlobalScope' are not identical.

ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts
ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts(18152,13):
TS2451: Cannot redeclare block-scoped variable 'navigator'.

ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts
ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts(18568,6):
TS2300: Duplicate identifier 'RequestInfo'.

ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts
ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.d.ts(18746,6):
TS2300: Duplicate identifier 'XMLHttpRequestResponseType'.

ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.iterable.d.ts
ERROR in /git_repository/react_styled-components/node_modules/typescript/lib/lib.dom.iterable.d.ts(67,11):

この問題を解決するためtsconfig.jsonを下記のように修正しました。

{
  "compilerOptions": {
    ...
    "skipLibCheck": true
  },
  ...
}
Buy me a coffeeBuy me a coffee
Posts