気持ち
ReactのComponentは、stateが更新されるとコンポーネントが丸っと再描画されます。このとき、Virtual DOMのおかげで差分のみがDOMに反映されるので、性能をそんなに劣化させる事なくUI制御をすることが可能になります。
でも、アプリで表示するデータがFBのタイムラインみたいに無限に取得できるような画面の場合、いくらVirtual DOMといえどもさすがに辛いのでは。さらに、もしそのデータがネストしていたら、実際に描画しないとしてもネスト部分のループ処理は行われるわけだよね?実際どうなの?
調べてみた
ということで、jsperfで実際にやってみました。
[
{
id: 1,
firstName: 'xxx',
lastName: 'XXX',
children: [...]
},
...
]
という感じのネストしたデータを大量に表示するコンポーネントを二つ用意し、一つは何も考えずにコンポーネントを定義、もう一つはshouldComponentUpdate
を使って、childrenの配列に変化がなければ(つまり !== で比較してfalseであれば)childデータの表示コンポーネントは再描画しない、というようにしています。
shouldComponentUpdate
は、コンポーネントを再描画するかどうかを決定するAPIで、defaultは常にtrueを返す、つまり常に再描画するようになっています。
https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate
結果はこちら
http://jsperf.com/react-performance-shouldcomponentupdate
(表示が重いのでブラウザ一瞬固まるかも。固まってもそっとしといて)
root2のほうがshouldComponentUpdate
を使った結果ですが、結果は明白ですね。
1秒間に10回再描画処理(実際には何もしてない)が走るのに対し、shouldComponentUpdate
を使わない方は1秒間に1回の描画すらできていません。
とはいえ
shouldComponentUpdate
を使うと、コンポーネントのメンテナンスコストも上がりますし、この差分チェックロジックにバグがあれば意図した通りにUIが反映されない、という辛いバグにぶつかるかもしれません。今回の例だと、dataコンポーネントの表示全体としては問題ないけど、なぜかchildlenデータ部分の表示だけおかしい、みたいなことが起きるかもしれません。FBが推奨するようにimmutable-jsとPureRenderMixinを組み合わることを考えた方が良いかも。
まとめ
性能面が問題になるくらいに複雑なデータを表示しないのであればこのAPIを使う必要はなさそうですが、万が一性能が問題になった時はshouldComponentUpdate
で回避できることを思い出そう。