俺が考えた最強の Reactのステートレスコンポーネントの書き方

最近自分はこう書いてるという例。意見が欲しい。
この記事に redux は出てこない。

参考: https://qiita.com/mizchi/items/bcb1aef8d1f14f8d0b4a

構成要素

  • React
  • flow
  • styled-components
  • recompose

以下 SFC = Stateless Functional Component

/* @flow */
import React from "react"
import styled from "styled-components"
import pure from "recompose/pure"

type Props = {|
  value: string
|}

export default pure(function Example(props: Props) {
  const { value } = props

  return (
    <Container>
      <Value>{value}</Value>
    </Container>
  )
})

const Container = styled.div`
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
`

const Value = styled.span`
  color: #f00;
`

解説

  • prettier: semi: false
    • ノーセミコロン派
  • /* @flow */
    • flow の有効化
    • デフォルト有効化は(主にnode_modules以下で勝手に死にまくるので)さすがにきつい
  • import styled from "styled-components"
    • 最近もう完全に styled-components の css-in-js でいいじゃん派になった
    • 実際流行ってる。便利
  • import pure from "recompose/pure";
    • SFC はデフォルト pure ではないので、パフォーマンスを気にする場合は pure を使う (extends React.PureComponent {} 相当)
    • flow-typed install recompose@0.x.x で型定義ファイルを入れておく
    • パフォーマンスを気にしないなら(後回しにするなら)サボっても良い
    • recompose/pure だけ使っておけばあわよくば参照絞れる
      • コンポーネント集だけのライブラリに切り出すときとか
  • type Props = {| ... |}
    • $Exact<...> 相当で完全一致を要求する。 指定された props 以外の値を与えられるとエラー
    • <Example onClick={...} onClickItem{...} > みたいに名前を変えた時にコードに残ってしまうことがあった
  • export default pure(function Example(props: Props) {
    • しない派閥もいるようだが、自分は export default 「しか」しない派
    • 代わりにファイル名とコンポーネント名は一致させる。なので UpperCamelCase
    • function <Name>() の Name 部分はReact が render後にコンポーネント名のデバッガとして使うので与えておく。これも面倒だったらサボって良い。その場合、 (anonymous) になる。
    • pure(...) すると PureComponent になってすべてのキーに shallow equal が比較され描画されるかどうか決まる
    • compose(pure)(Component) とすると 型が消えてしまう(合成されたものに対して片づけし直す必要がある)ので、複雑なことをしないSFCなら pure だけ使う
  • const { value } = props
    • 関数内で、値が SFC の props か React.Component のときの this.props, this.state か、というコンテキストを除くために、一旦使う値を全部バラしてしまう
    • 一度バラしてしまえば他のコンテキストに移した時のリファクタで便利
  • const Container = styled.div
    • styled-components はそのファイルスコープ内の export default の後に書く習慣にしている。
    • ファイルを開いた時に export default` を目視するコストを少なくしたい
    • 大抵 Container みたいな名前のラッパーを書く
    • コンポーネント志向だと 縦横 100%, 100% の display: flex になることが多い
    • 本当は web/react-native の抽象化のために https://github.com/lelandrichardson/react-primitives を使いたいが、時代が追いついてきてない
    • atom の language-babel 入れてると css でハイライトされるし、 prettier のCSS整形も掛かる

省エネ版

デバッガの情報を減らしてでもショートハンドで横着する人向け

/* @flow */
import React from "react"
import styled from "styled-components"

export default ({value}: {| value: string |}) =>
  <Container>
    <Value>{value}</Value>
  </Container>

const Container = styled.div`
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
`

const Value = styled.span`
  color: #f00;
`