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

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

ランサーズ 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日目の記事でした。

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

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)