22
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Lancers(ランサーズ)Advent Calendar 2018

Day 9

styled-componentsを使ったReactコンポーネント作成入門

Last updated at Posted at 2018-12-08

ランサーズ Advent Calendar 2018」9日目の記事になります。
昨日は、「ランサーズでインターンをして感じたプログラミング学習における個人とチームの違い」でした。

ランサーズはいくつかReactのプロダクトがあるのですが、スタイルはcss-modulesを使用して書いていました。
最近Reactの開発にstyled-componentsを採用したところ、非常に書き心地が良かったので紹介します。

styled-componentsとは

styled-copmonentsはJavaScriptのファイルの中でcssを定義するためのライブラリで、いわゆるCSS in JSの一種です。

styled-componentsはstyled.[タグ名]`[css]`でスタイルをあてたコンポーネントを作成することができます。
作成したコンポーネントは変数名をタグ名にして使うことができます。

App.jsx
import styled from "styled-components";

const Title = styled.h1`
    font-size: 30px;
  color: red;
`;

const App = () => (
  <Title>タイトル</Title>
)

ちなみにstyled.h1にテンプレートリテラル(``)が続いている構文が見慣れないかもしれないですが、これはタグ付きテンプレートリテラルと呼ばれる構文です。

コンポーネントを作ってみる

styled-componentsを使って下の画像のようなボタンのコンポーネントを作ってみます。

このボタンはdefault・Primary・Dangerの三種類の色があります。
また大きさが2種類、disabledとそうではないパターンが存在します。

スクリーンショット 2018-12-08 12.12.48.png

最終的なコードはこちらに置いてあります。

共通部分をつくる

はじめにdefaultのボタンを作り、すべてのパターンに共通する箇所のスタイルをあてます。
ここでは、フォントのサイズや丸みをつけたり、ホバー時のカーソルがポインターになるようにしています。

共通部分をつくる
const Button = styled.button`
  font-size: 1rem;
  padding: 5px 10px;
  border-radius: 5px;
  cursor: pointer;
`;

const App = () => (
  <div>
    <Button>Button</Button>
  </div>
)

スクリーンショット 2018-12-08 11.32.31.png

色を変える

次に色を変えてみます。
今回はdefaultとPrimary、Dangerの3タイプのボタンが使えるようにします。

色を変える
const Button = styled.button`...`;

const PrimaryButton = styled(Button)`
  border: none;
  color: white;
  background: #007bff;
`;

const DangerButton = styled(Button)`
  border: none;
  color: white;
  background: #dc3545;
`;

const App = () => (
  <div>
    <Button>Button</Button>
    <PrimaryButton>Primary</PrimaryButton>
    <DangerButton>Danger</DangerButton>
  </div>
)

styled([コンポーネント名])で既存のコンポーネントに対してstyleを追加することができます。
ここではdefaultのbuttonにbackgroudやcolorを追加して新しいコンポーネントPrimaryButton,DangerButtonを作っています。

スクリーンショット 2018-12-08 11.32.10.png

大きさを変える

defaultのサイズに加えて、大きいサイズのボタンが使えるようにします。
コンポーネントのpropsにlargeを与えることでサイズを変更できるようにします。

大きさを変える
const Button = styled.button`
  font-size: 1rem;
  padding: ${props => (props.large ? "10px 15px" : "5px 10px")};
  border-radius: 5px;
  cursor: pointer;
`;

const PrimaryButton = styled(Button)`..`;
const DangerButton = styled(Button)`...`;

const App = () => (
  <div>
    <div>
      ...
    </div>
    <div>
      <Button large>Button</Button>
      <PrimaryButton large>Primary</PrimaryButton>
      <DangerButton large>Danger</DangerButton>
    </div>
  </div>
)

cssはテンプレートリテラルを使って記述するので${}の中に変数などを入れることができます。
またstyled-componentsで${}の中に関数を与えることもでき、第一引数はコンポーネントのpropsになります。

上のコードではpropsにlargeが与えられた場合とそうでない場合で、paddingを変えています。

スクリーンショット 2018-12-08 11.51.49.png

disabledのときにスタイルを変える

ボタンがdisabledのときに色とカーソルの形状を変えます。
大きさを変えるときと同様にpropsにdisabledが与えられたときにスタイルを変えます。

disabledのときにスタイルを変える
import styled, { css } from 'styled-components';

const Button = styled.button`
  ...

  ${props => props.disabled && disabledCss}
`;

const disabledCss = css`
  opacity: 0.5;
  cursor: default;
`;

const PrimaryButton = styled(Button)`..`;
const DangerButton = styled(Button)`...`;

const App = () => (
  <div>
    ...
    <div>
      <div>
        <Button disabled>Button</Button>
        ...
      </div>
      <div>
        <Button large disabled>Button</Button>
        ...
      </div>
    </div>
  </div>
)

css``はcssを変数化して、そのcssをテンプレートリテラル内に挿入したい場合に使います。
ここではdisabledの場合のスタイルを変数化して、propsのdisabedが存在した場合に挿入しています。

これで完成です。

スクリーンショット 2018-12-08 12.12.48.png

css-modulesとの比較

同じものをcss-modulesで作ろうとすると下のようになると思います。

css-modulesの場合
import React from 'react';
import styles from './styles.css';

function createButton(type) {
  return ({children, large, disabled}) => {
    const classNameList = [styles.button, styles[type]]
    if (large) {
      classNameList.push(styles.large)
    }
    if (disabled) {
      classNameList.push(styles.disabled)
    }
    return (
      <button className={[styles.button]}>{children}</button>
    )
  }
}

const Button = createButton('default');
const PrimaryButton = createButton('primary');
const DangerButton = createButton('danger');

比較をするとstyled-componentsには以下のような利点があると考えます。

  • styled-componentsの中だけで完結する。簡単なコンポーネントであればreactをimportする必要すらない。
  • css-modulesでスタイルを変えることは最終的にclassNameに与える文字列をどうやって生成するかに帰着する。そのためこのような簡単なコンポーネントでも複雑なロジックが発生する。styled-componentでは複雑化しない。
  • 一つのファイルで完結するので見通しが良い。

まとめ

styled-componentsを使ってボタンのコンポーネントを作成しました。
css-modulesと比較をすると簡潔なコードでコンポーネント作成ができていることがわかると思います。

以上、「ランサーズ Advent Calendar 2018」9日目の記事でした。

明日は「ランサーズエンジニアのキーボードの世界」です。お楽しみに!

22
10
1

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
22
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?