JavaScript
TypeScript
reactjs
styled-components

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

最近、仕事で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を対象にしています。