今回はComponentのlifecycleについて書きたいと思います。
React.jsではComponentの状態の変化に合わせて色々メソッドを呼んでくれるのでそれに合わせて初期化や後始末な処理を書くことが出来ます。
よく使うのはcomponentDidMount
やcomponentWillUnmount
辺りです。
イベントの登録をcomponentDidMount
でやってcomponentWillUnmount
で解除するというのがよく使うパターンだと思います。
componentWillMount()
ComponentがDOMツリーに追加される前に一度だけ呼ばれます。
なので初期化処理を行うのに適しています。
この中でsetState
するとrender時にまとめて行われます。
server-side rendering時にも呼ばれるのでどちらでも動くコードである必要があります。
componentDidMount()
ComponentがDOMツリーに追加された状態で呼ばれるのでDOMに関わる初期化処理を行いたい時に便利です。
componentWillMountと違いserver-side renderingの時には呼ばれません。
DOMを扱う処理のほか、AjaxリクエストやsetIntervalの登録などのserver-side rendering時には必要ない初期化処理についてはこの中でやることになります。
componentWillReceiveProps(nextProps)
Propが更新される時に呼ばれます。ちなみにComponentが新しくDOMツリーに追加される時には呼ばれません。
親ComponentのStateがPropとして渡されていて、その値が変化した時に画面の表示以外で何かしたいときに使う感じです。Notification的な?
後はPropの値に応じてStateの値を更新したいようなときに使います。
shouldComponentUpdate()
これだけは他のlifecycleメソッドと違い、true
かfalse
を返す必要があります。
Componentがrerenderされる前に呼ばれ、false
を返すとVirtualDOMの比較を行わずにrerenderもされなくなります。
なので独自でPropやStateを比較するような処理を実装することで無駄な計算をなくし、Performanceの向上を行うことを目的に実装します。
デフォルトでは常にtrue
を返すようになっているので常にrerenderされます。
また、forceUpdate
という強制的にrerenderするメソッドもあるのですがそれが呼ばれた場合にはこのメソッドは呼ばれません。
PropやStateを完全にImmutableなデータにして単純なObjectの比較にすることが可能になります。
shouldComponentUpdate: function(nextProps, nextState) {
return nextProps.user !== this.props.user || nextState.user !== this.state.user;
}
componentWillUpdate(nextProps, nextState)
Componentが更新する前に呼ばれます。初回時には呼ばれません。
この中でsetState
を呼ぶことは出来ないのでPropの値を元にsetState
したいような場合はcomponentWillReceiveProps
を使います。
componentDidUpdate(prevProps, prevState)
Componentが更新された後に呼ばれます。初回時には呼ばれません。
DOMの変化にフックして何かしたい場合に使うと便利です。
componentWillUnmount()
ComponentがDOMから削除される時に呼ばれます。
イベントの解除などクリーンアップ処理をしたいような場合に使うと便利です。
ComponentDidMountで登録したTimerの処理やDOMのイベントはここで解除するべきです。
おまけ
isMounted
例えばAjaxリクエストしてその結果をsetStateすることはよくあると思いますが、その時にリクエストが帰ってきた時にはすでにComponentがUnmountされていることもあり得ます。
その時にsetState
やforceUpdate
を呼んでしまうとエラーになるのでisMounted()
でガードしておく必要があります。
componentDidMount() {
request.get('/path/to/api', res => {
if (this.isMounted()) {
this.setState({data: res.body.data});
}
});
}
今回はComponentのLifecycleについて紹介しました。
明日は、Eventについて書きたいと思います。