Help us understand the problem. What is going on with this article?

React.jsのComponent Lifecycle

More than 5 years have passed since last update.

今回はComponentのlifecycleについて書きたいと思います。

React.jsではComponentの状態の変化に合わせて色々メソッドを呼んでくれるのでそれに合わせて初期化や後始末な処理を書くことが出来ます。

よく使うのはcomponentDidMountcomponentWillUnmount辺りです。
イベントの登録を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メソッドと違い、truefalseを返す必要があります。
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されていることもあり得ます。
その時にsetStateforceUpdateを呼んでしまうとエラーになるのでisMounted()でガードしておく必要があります。

componentDidMount() {
  request.get('/path/to/api', res => {
    if (this.isMounted()) {
      this.setState({data: res.body.data});
    }
  });
}

今回はComponentのLifecycleについて紹介しました。
明日は、Eventについて書きたいと思います。

koba04
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした