LoginSignup
30
25

More than 5 years have passed since last update.

styled-componentsを使った雑なReact Presentational Componentの書き方

Last updated at Posted at 2018-03-17

最近、仕事でReactを書く機会が多くなってきて色々試しているうちに書き方が落ち着いてきました。

[注意]

本来はクラス毎にStyledComponentsのインスタンスを作った方がいいです。自分がVueライクな感じで雑に書くための記法です。

この表記ですと、子コンポーネントに同じクラス名があたったときに、親コンポーネントのスタイルが当たるので完全なscopedなスタイルにはなりません。
@nabeliwoさんにコメントいただきました。ありがとうございます!)

既にHTMLが存在しているときに雑にReactに移植するときの途中段階とかで役立つ書き方です

TodoItem.jsx
import React from 'react'
import styled from 'styled-components'

const TodoItem = ({
  className,
  title,
  description,
  onDestroy,
}) => (
  <div className={className}>
    <div className='title'>{title}</div>
    <div className='description'>{description}</div>
    <span className='close'></span>
  </div>
)

export default styled(TodoItem)`
  margin: 12px 0;
  padding-bottom: 12px;
  border-bottom: 1px solid #e5e5e5;

  .title {
    font-weight: bold;
    font-size: 15px;
  }

  .description {
    opacity: 0.8;
    font-size: 12px;
  }
`

ポイント

  • styled-componentsでCSSのsyntaxのままJS内に埋め込めるようになったこと
    • 今までCSS in JSはキャメルケースのスタイルが嫌だったので使ってなかった。
    • 少なくともVSCodeではプラグインがあってうまく動いてる
  • styled-componentsで作ったスコープの中でのみ効くスタイルを書く
    • CSS Modulesの考え方から
    • classNameに勝手に割り振ってくれて擬似的なスコープが出来る。
    • exportで吐き出す時に書いて、一箇所にスタイルをまとめる
      • 公式のサンプルでは各パーツごとに定数を定義していって、それを組み合わせる形にしているので推奨される書き方ではなさそう
    • 子コンポーネントに同じクラス名があたったときに、親コンポーネントのスタイルが当たるので完全なscopedなスタイルではない
  • HTML, CSS, JSが1ファイルになる
    • Vue.jsライクなファイル構成になる。半年前ぐらいまでVue.jsばっか書いてたから嬉しい
  • AtomicDesignの尺度とは違う。もう少しざっくり書く時に使える。
    • アプリケーションを作り始めるタイミングではこのぐらいのサイズ感で書くと早い(気がする)
  • Componentがでかくなるとファイルを分けたくなるので、小さく保つ意識が持てるかも

TypeScript

TodoItem.tsx
import * as React from 'react'
import styled from 'styled-components'

const TodoItem : React.StatelessComponent<{
  className?: string
  title?: string
  description?: string
  onDestroy?: Function
}> = ({
  className,
  title,
  description,
  onDestroy,
}) => (
  <div className={className}>
    <div className='title'>{title}</div>
    <div className='description'>{description}</div>
    <span className='close'></span>
  </div>
)

export default styled(TodoItem)`
  margin: 12px 0;
  padding-bottom: 12px;
  border-bottom: 1px solid #e5e5e5;

  .title {
    font-weight: bold;
    font-size: 15px;
  }

  .description {
    opacity: 0.8;
    font-size: 12px;
  }
`

Reactはv16、参考例のTypeScriptはv2.7を対象にしています。

30
25
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
30
25