ReactのライフサイクルやPureComponentについて
今回はReactのライフサイクルやPureComponent辺りについて紹介したいと思います。
早速ですが、ライフサイクルはMounting、Updating、Unmounting、Error Handlingがあります。(今回の記事ではUnmountingとError Handlingについては紹介しません。)
Mounting
以下のメソッドは、コンポーネントのインスタンスを作成してDOMに追加される時に呼び出されます。呼び出される順番は以下の順番です。
- constructor()
- static getDerivedStateFromProps()
- render()
- componentDidMount()
Updating
以下のメソッドはコンポーネントが再レンダリングされる時に呼ばれます。
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
ここで重要なのはshouldComponentUpdate
です。
コンポーネントがrenderされる前に呼ばれます。
このメソッドは、nextProps
, nextState
を受け取り現在のpropsとstateを比較します。更新するときはtrue
を更新が必要ない場合はfalse
を返します。
注意したいのは、React.Component
の場合はshouldComponentUpdateはデフォルトでtrueを返すということです。
なのでReact.Component
の場合はshouldComponentUpdate
でロジックを書く必要があります。
簡単な例
type Props = { name: string; age: number; } class User extends React.Component<Props> { shouldComponentUpdate(nextProps:Props) { if(this.props.name === nextProps.name) { return true } else { return false } } /* 以下省略 */
例えば親のコンポーネントの状態だけが変更し、子のコンポーネントのpropsやstateに変化がない場合に子のコンポーネントも一緒にマウントされます。そうするとコンポーネントの描画速度が遅くなります。ですのでReact.Component
で書く場合は、ちゃんとshouldComponentUpdate
を使って描画パフォーマンスを最適化してあげる必要があります。
React.PureComponent
次に最初の方で挙げたReact.PureComponentについてです。
結論を先に言うとReact.PureComponent
はshouldComponentUpdate
の処理が実装済みとなっています。ですのでReact.PureComponent
を使うのが良いでしょう。ですがここで注意したいのは、React.PureComponentのshouldComponentUpdate
はshallow compareするので以下のケースの場合、常にマウントされる結果となります。
class App extends React.PureComponent { render() { return ( <div className="App"> <User families={{ brother: 2, sister: 1 }} name="sato" age={20} /> </div> ); } }
propsにはつねに新しいオブジェクトを受け取っています。
shallow compareなのでプロパティと値が正しくてもshouldComponentUpdate
の戻り値はtrue
を返してしまいます。今はオブジェクトの階層は深くありませんが、もっと階層がある場合などこのような場合などを考慮するとPureComponent
の受け取るpropsやstateなどはシンプルなものにすると良いでしょう。また深い階層でpropsやstateの値が変更されるとわかっている場合は、forceUpdate()
を使うのも一つの方法です。
Shallow Compareについて
Pure.Component
がリリースされる前は、Shallow Compareを使用していました。このアドオンがPure.Component
の役割を果たしていました。
以下のように使います。(公式サイトから引用)
// インポートする方法 import shallowCompare from 'react-addons-shallow-compare'; // ES6 var shallowCompare = require('react-addons-shallow-compare'); // ES5 with npm
shallowCompare
メソッドには同じようにnextProps
とnextState
を渡してあげます。そうすることでshallowCompareが比較してくれます。
export class SampleComponent extends React.Component { shouldComponentUpdate(nextProps, nextState) { return shallowCompare(this, nextProps, nextState); } render() { return <div className={this.props.className}>foo</div>; } }
まとめ
Reactのコンポーネントの描画する仕組みを知っておくことで、最適な描画パフォーマンスを実現できると思います。 今回紹介したもの以外にReact.memoやrecomposeのpureなどがあるので次はこれらについて紹介したいと思います。