Edited at

reactのshouldComponentUpdateについて

More than 3 years have passed since last update.


気持ち

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で回避できることを思い出そう。