React Component ライフサイクル ひとめぐり (CodeSandbox 付き)
書籍『はじめてのフロントエンド開発』が2018年5月9日に技術評論社さまより刊行されております。
執筆プロジェクトでは React のパートを担当させていただいたのですが、執筆にあたり作成した React Component ライフサイクル に関する図 をこのたび CC0 ライセンスで公開しました。
.ai
および .svg
フォーマットも取り揃えておりますのでどうぞご活用ください。
ところでお気づきの方もいらっしゃると思いますが、書籍執筆時点では React v16.3 のリリース前であったため、上記のダイアグラムも v16.3 で追加されたライフサイクルについての情報が盛り込まれていません。
更新版を作成する意思を見せつつ(言い訳)、今回は、React Component ライフサイクルのメソッドについて改めて整理しようという目的で筆を執りました。
Sand Box 的な何か
本エントリで登場するメソッドたちを利用したごく簡単なサンプルアプリを公開しています。
あらためて、React の Component ライフサイクルに関するメソッドについて
"React の Component ライフサイクルに関するメソッド" についての情報は公式ドキュメントにまとまっています。
詳細は公式ドキュメントをご覧いただくとして、各メソッドについて簡単に整理します。
componentDidMount()
componentDidMount()
は Component が Mount された後に実行されるメソッドです。用途の例は以下のとおりです。
- Ajax を使ったデータフェッチを行う(初回)
- DOM に対する処理を行う(初回)
- タイマーをセットする
- イベントリスナのセット
fetch()
を利用してデータフェッチを行う例です。
fetchUser = (name: string) => { fetch(`https://api.github.com/users/${name}`) .then(res => res.json()) .then(json => this.setState({ gitHubUser: json as GitHubUser })); }; componentDidMount() { this.fetchUser(this.props.name); }
SandBox では GitHub の API を利用して指定したユーザーの Avatar を表示とタイマーのセットを行っています。
componentDidUpdate()
componentDidUpdate()
は、Component の props
または state
が変更されたときに実行されます。用途の例は以下のとおりです。
- Ajax を使ったデータフェッチを行う(二回目以降)
- DOM に対する処理(二回目以降)
- その他諸々
componentDidMount()
は一度のみ実行されます。初回のデータフェッチは componentDidMount()
に記述し、props
ないし state
の変更に応じて再フェッチする場合 componentDidUpdate()
にも処理を書くことになります。
componentDidMount() { // 初回のフェッチ this.fetchUser(this.props.name); } componentDidUpdate(prevProps) { // props.id が変更されたら再フェッチ if (this.props.name !== prevProps.name) { this.fetchUser(this.props.name); } }
SandBox では Select Box の 状態が変更された場合、GitHub の API を再び呼び出す処理を記述しています。
componentDidMount()
に無限ループするようなロジックを書いてしまいがちですので注意します。
// 無限にアップデートされ続ける componentDidUpdate(prevProps: Props, prevState: State) { this.setState({ count: prevState.count++ }); }
componentWillUnmount()
componentWillUnmount()
は Component が Unmount されるときに実行されます。componentDidMount()
で行った処理の解除を行うことが多いでしょう。
- タイマーを解除する
- イベントリスナを解除する
- 非同期処理を中止する
componentWillUnmount() { clearInterval(this.timerId); }
getDerivedStateFromProps()
v16.3 で新設のメソッドです。戻り値とした Object の内容で state
が更新されます。戻り値がない場合は state
は更新されません。
static getDerivedStateFromProps(nextProps: Props, prevState: State) { const name = nextProps.name.toUpperCase(); if (prevState.name !== name) { return { isDerivered: true, name }; } return; }
上記のサンプルはかなり苦肉の策感がありますが、実際、props
の値をレンダリングに使うだけという場合、わざわざ state
として管理する必要はありません。「初期値を props
から求める + ユーザーの操作に応じて state
の値が変更される」ような場合に利用します。
getDerivedStateFromProps()
は static method のため、メソッド内で this.props.hoge !== nextProps.hoge
のような比較処理は行えません。この点において componentWillReceiveProps()
の代替ではない点に注意します。
shouldComponentUpdate()
shouldComponentUpdate()
は、不要な再レンダリングを抑制してパフォーマンスの低下を防ぐ目的で利用されます。
shouldComponentUpdate(nextProps: Props, nextState: State) { // isVisible が変更されたときだけ再レンダリングを行う if (this.state.isVisible !== nextState.isVisible) { return true; } return false; } // shouldComponentUpdate() により props.text が更新されただけでは再レンダリングされない render() { return <div> {this.state.isVisible && <p>{this.props.text}</p>} </div> }
ただし、レンダリングに利用する値かどうかを shouldComponentUpdate()
で判断してレンダリングのコントロールを行うことは適切ではありません。レンダリングに使用しない(が状態が変更される)ものは Class のメンバ変数として扱い state
として管理しないようにします。
shouldComponentUpdate(nextProps: Props, nextState: State) { // (動作上は問題ないが) render() 内で利用しない状態をここで比較しているということは // そもそも state では無い説 if (this.state.timerId !== nextState.timerId) { return false; } return true; }
getSnapshotBeforeUpdate()
v16.3 で新設のメソッドです。getSnapshotBeforeUpdate()
は、Component の再レンダリングが行われる直前に実行されます。戻り値がある場合、componentDidUpdate()
の第三引数に値が渡ります。
getSnapshotBeforeUpdate()
の用途としてスクロールポジションの管理に使う例が提示されています。
componentWillReceiveProps()
v1.7 で廃止予定。これまで componentWillReceiveProps()
で行っていた処理は getDerivedStateFromProps()
ないし componentDidUpdate()
に移管できるはず。
componentWillUpdate()
v1.7 で廃止予定。同様に getDerivedStateFromProps()
ないし componentDidUpdate()
で代替できるはず。
componentWillMount()
v1.7 で廃止予定。使用しない。
書籍について
冒頭で言及した『はじめてのフロントエンド開発』は、パンダの表紙が目印の通称パンダ本です。
本エントリで触れた Component ライフサイクルを始め、React の "さわり" を眺めつつ、React を使った SPA を実装する流れです。TypeScript + React に挑戦してみたい方にもお勧めできます。
React、Angular、Vue.js、React Nativeを使って学ぶ はじめてのフロントエンド開発
- 作者: 原一浩,taisa,小松大輔,永井孝,池内孝啓,新井正貴,橋本安司,日野洋一郎
- 出版社/メーカー: 技術評論社
- 発売日: 2018/05/09
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
特徴としてはパンダが可愛いことです (語彙力)。
書籍で解説しているコードは下記の Repository で公開しています。あわせてご参照ください。
共著者のブログ
以上です。