Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

React コンポーネントのライフサイクルとメソッドの役割について

More than 1 year has passed since last update.

公式ドキュメント React.Component を読んだメモです。

コンポーネントのライフサイクルと、実行されるメソッド

React Lifecycle Methods Diagram より。
20181122145036.png

太字が主要なライフサイクルメソッド。constructor()render()componentDidMount()componentDidUpdate()componentWillUnmount()

前提

props は、コンポーネントの外から来る値。親コンポーネントから受け継ぐ。変更不可。
state はコンポーネント内のプライベートな値。変更可。この state は Redux の state とは別物。コンポーネントの状態。
両方の値がレンダリング結果に影響する。

主要なライフサイクルメソッドの役割

constructor(props)

2つの用途にのみ使う。

  • this.state の初期化
  • イベントハンドラの bind
constructor(props) {
  super(props);
  // ここで this.setState() を使ってはいけない
  this.state = { counter: 0 };
  this.handleClick = this.handleClick.bind(this);
}
  • propsthis.state にコピーしてはダメ
  • this.state に直接代入していいのは、コンストラクタのみ。他は this.setState() を使う
  • コンストラクタで副作用を発生させないこと。そういう時は componentDidMount() を使う

render()

コンポーネントで唯一の必須メソッド。

this.propsthis.state を読んで、以下のどれかを返す。

  • React elements - JSX などで作る
  • Arrays and fragments - 複数の elements を返す
  • Portals - 別の DOM ノードにレンダリングする
  • String and numbers - テキストとしてレンダリングする
  • Booleans or null - なにもレンダリングしない。return test && <Child />testfalse の場合、Boolean が返って何もレンダリングしない

render() は pure な function であるべき。

  • コンポーネントの state を変えない
  • 同じ入力に対して毎回同じ結果を返す
  • ブラウザと直接インタラクトしない。インタラクトするには componentDidMount() など他のメソッドを使う

shouldComponentUpdate()false を返したら実行されない。

componentDidMount()

  • コンポーネントがツリーにマウントされた時に実行される
  • DOM ノードが必要になるような初期化処理はここでやる
  • ネットワークへのリクエストをここでやる
  • subscription をここでやって、componentWillUnmount() で unsubscribe する

componentDidMount()setState() を実行すると追加のレンダリングが実行される。この時、ブラウザが画面を連続して描画したりはしない。2回 render() が実行されても、途中の画面の変化をユーザが目にすることはない。

画面が変わらなくても、パフォーマンスには影響するので注意。

componentDidUpdate(prevProps, prevState, snapshot)

  • 初回は実行されない。更新時に実行される
  • コンポーネントが更新されたタイミングで DOM を操作したいときは、ここでやる
  • 更新前後の props を比較して、ネットワークにリクエストしたいときは、ここでやる
  • setState() を実行するときは、条件を設定する。条件無しだとループする
    • レンダリング → setState() → レンダリング → setState() → …
  • componentDidMount() と同じく、再レンダリングの過程は画面に描画されないけれども、パフォーマンスには影響し得る

componentWillUnmount()

  • コンポーネントがアンマウントされるときに実行される
  • クリーンアップの処理をここでやる
    • タイマーの無効化
    • ネットワークリクエストのキャンセル
    • unsubscribe
  • もうレンダリングされないので、setState() を呼んではいけない

レアなライフサイクルメソッド

shouldComponentUpdate(nextProps, nextState)

パフォーマンスの目的でのみ使用する。

今のところ、false を返すとレンダリングが実行されないが、将来は、場合によってレンダリングするように変更される可能性がある。このメソッドの結果が、厳密な制御ではなくヒントとして使われるようになる可能性がある。

getDerivedStateFromProps(props, state)

使わない。

getSnapshotBeforeUpdate(prevProps, prevState)

DOM が変化する前の値をとっておいて、componentDidUpdate(prevProps, prevState, snapshot) の3番目の引数で受け取って使う。

Redux と一緒に使う場合

Redux と一緒に使う場合、ライフサイクルメソッドの componentDidMountcomponentDidUpdatecomponentWillUnmount から、アクションを dispatch できる。

rendercomponentDidMount → (Redux の) state 変更 → render のように 2回レンダリングすることになるが、受け入れる。2回 render() しても、画面の書き換えは1回だけ。

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