どう考えているか、というのを聞かれたので、記事に起こしておきます。個人の意見です。
Prettier を使う
気づけばコードの整形を人間がやる時代は終わりました。
細かいコーディングスタイルでレビューの時間を取るぐらいだったら、一貫した自動整形ルールを適用すべきです。
人によっては細かいこだわりがあって prettier の規則が気に食わないかもしれず、僕も最初はそうでしたが、Atomで保存する度に自動整形を走らせる prettier の強烈な開発体験によって、最終的にそれらのこだわりを全て捨てることが出来ました。
生産性を求めるなら、現時点では最優先で導入すべきものです。
React.createClass を使わない
v16 で削除されたのでいわずもがな。
同様に、 createClass でしか使えなかった mixin 周辺機能も丸ごと deprecated です。
「可能な限りは」 Stateless Fuctional Component を使う
悪い例
これはアンチパターンとは言い切れないけど、今ではあまりいいコンポーネント定義ではない例です。
class App extends React.Component {
componentDidMount() {
console.log('mounted')
}
render() {
return <span>Hello</span>
}
}
理由
クラスベースの設計は状態を内部で抱えがちで、React.Component の内部においては state は好まれません。プレゼンテーショナルなレイヤーだということを明示するために、state に触らない限りは extends React.Component
は推奨しません。
現実的には、state は完全に排除出来ないとは思いますが、 state を持つ component は特殊なコンテナーであって、出来る限り抑えるべきです。
それを機械的に検出するのに eslint-plugin-react/prefer-stateless-function をおすすめしています。
代替
HOC + Functional Stateless Component
とりあえずは recompose を使うのを推奨しています。
import { lifecycle } from 'recompose'
lifecycle({
componentDidMount() {
console.log('hello')
}
})(function App () {
return <span>Hello</span>
})
複数の HOC を使う場合は compose を使います。
import { compose, lifecycle, pure } from 'recompose'
compose(
lifecycle({
componentDidMount() {
console.log('hello')
}
}),
pure
})(function App () {
return <span>Hello</span>
})
redux を使っているならば、 コールバックから dispatch することはあっても、状態そのものは component 内部に残らないはず。
結果として、 extends する React Component はほとんどいなくなるはずです。
内部関数で子Component を render しない
悪い例
よく見る駄目な例。
class Layout extends React.Component {
renderHeader() {
return <header/>
}
render() {
return <div>
{this.renderHeader()}
{this.props.children}
</div>
}
}
良い例
責務に則って分割します。
function Header() {
return <header/>
}
function Layout({children}) {
return <div>
<Header/>
{children}
</div>
}
本当に必要になるまで ImmutableJS を使わない
理由
これは議論の余地があるとは思っているのですが、自分の経験上、 Immutable JS は、一部のドメインを無駄にややこしくするだけで、理解せずに使うとパフォーマンス問題を解決するツールなのに重篤なパフォーマンス問題を引き起こしがちで、そしてほとんどの人はこれを使う意味を理解していません。とくにチーム開発においては、百害あって一理なしだと思っています。
代替
ES2015 の object-rest-spread を使う
const prev = { a: 1, b: 1 }
const next = { ...prev, b: 2}
Reactの差分検知で、オブジェクト参照が同じままその内部状態を抱えてしまうと、変更検知されない可能性があります。
もっと攻めたルールだと、React に限らずオブジェクトのメンバへの再代入禁止、もありえます。あらゆるオブジェクトは暗黙にイミュータブルとして扱うというわけです。自分の個人プロジェクトはそれで運用して、ちゃんと回っています。
PropTypes はもう使わない
理由
shape や required といった特殊な記法を覚えさせられるのに、ランタイムチェックしか出来ない、というのは静的解析ツールが充実した今では、二重定義になり足枷になりつつあります。
おそらくですが、Facebookの中の人達はもう使ってないです。古い時代の名残で残ってる機能のように見えます。この機能に限らず、Reactの機能が拡充される方向性は、Facebook社自身の内部での使い方に強く依存します。
代替案
Flow / TypeScript を使ってください。どちらも JSX の props の型情報を静的に検証できます。
Action定義では Flux Standard Action に従う
React からやや外れますが、Action 定義で FSA に準拠していない人が多いです。
一部の redux middleware は正しくFSAに準拠しないとちゃんと動かなかったりします。
悪い例
{
type: 'move-to',
x: 1,
y: 3
}
良い例
{
type: 'move-to',
payload: {
x: 1,
y: 3
}
}
まとめ
- Prettier を使う
- Stateless Component を優先する
- プレゼンテーショナルでない振る舞いの定義は HOC で行う
- PropTypes より flow/typescript を使う
- FSAに従う
- JSのオブジェクトをイミュータブルだと思い込んで使う