【React入門⑧】コンポーネントのライフサイクルを理解する
こちらの記事は、React入門チュートリアルです。
Reactが初めての私がReactを実装していく流れとなるため、初心者の方のつまずきやすいポイントを一通りフォローアップできる内容となっています。
ライフサイクルとは?
ライフサイクルとは、コンポーネントが描画され、イベントなどで値が変更されて再描画され…といったコンポーネントの描画までの「生まれてから死ぬまで(ライフサイクル)」として表したものです。
ライフサイクルを表現するためにはいくつかのメソッドが存在しますが、
以前のチュートリアルで扱っていた
- constructor
- render
もライフサイクルメソッドです。
ライフサイクルメソッドの分類
ライフサイクルメソッドは3種類に分類することができます。
- Mount系ライフサイクルメソッド = コンポーネントが認識されて使える状態になる
- Update系ライフサイクルメソッド = コンポーネントが更新される
- Unmount系ライフサイクルメソッド = コンポーネントが使えない状態になる
さらに詳しくライフサイクルメソッドを具体的に見ていきます。
componentWillMount
コンポーネントが描画される直前に実行される。初期化処理などに利用されています。
もしこのメソッドの中でsetStateをした場合、更新後の処理が描画されることになります。
ただしこちらのメソッドはReact v17.0で廃止予定です!(2019/9月時点で最新版は16.9)
componentDidMount
コンポーネントの初回の描画が行われた際に発動するライフサイクルメソッド。
すでにDOMが描画されているため、他のDOMに対するアクセスも可能となっています。
componentWiilReceiveProps
コンポーネントがPropsから値を渡された際に発動するライフサイクルメソッド。
Propsが値を渡すごとに更新されます。
shouldComponentUpdate
StateやPropsのデータが更新されているかどうかを検証し、更新されていれば再描画が行われるライフサイクルメソッド。
StateやPropsが更新されていればtrue、されていなければfalseを返します。
componentWillUpdate
コンポーネントが再描画される(PropsやStateの値が変わる)直前に発動するライフサイクルメソッド。最初の描画時に呼び出されないところが、componentWiilReceivePropsとの違いでしょう。
componentDidUpdate
コンポーネントが再描画された後に発動するライフサイクルメソッド。こちらも最初の描画時には呼び出されません。
componentWillUnmount
コンポーネントがDOMから削除される直前に発動するライフサイクルメソッド。
後にご紹介するsetIntervalメソッドに対するclearIntervalメソッドの配置場所などでよく使われます。
getDerivedStateFromProps
インスタンス化された後に、引数として渡されたPropsやStateを受け取ることができるライフサイクルメソッド。
ライフサイクルメソッドを使ってみる
早速ライフサイクルメソッドを使用してみましょう!
componentDidMountを使った例
import React, {Component} from 'react'; import ReactDOM from 'react-dom'; class App extends Component { constructor(props) { super(props); // stateのtitleに空文字を渡す this.state = {title:''}; } // コンポーネントが描画された際にstateのtitleに文字列を渡す componentDidMount() { this.setState({title:'Laravelとねころっけくん5.8'}) } render() { return ( <div> <h2>{this.state.title}</h2> </div> ); } } ReactDOM.render( <App />, document.getElementById('root') ); export default App;
このようなコードを記述すると、componentDidMountで渡した文字列が描画されていることがわかります。componentDidMountはコンポーネントが描画された直後に発動するライフサイクルメソッドでしたね。
ライフサイクルメソッドを複数使用したコンポーネント
React公式から拝借したライフサイクルメソッドを複数使用したコンポーネントを見てみましょう。
src/index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import * as serviceWorker from './serviceWorker'; ReactDOM.render(<App />, document.getElementById('root')); serviceWorker.unregister();
src/App.js
import React, {Component} from 'react'; import ReactDOM from 'react-dom'; class App extends Component { constructor(props) { super(props); this.state = {date: new Date()}; } componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); } componentWillUnmount() { clearInterval(this.timerID); } tick() { this.setState({ date: new Date() }); } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div> ); } } ReactDOM.render( <App />, document.getElementById('root') ); export default App;
これで以下のようなコンポーネントの動きになります。
App.jsのライフサイクルがどのように動いているのか見ていきましょう。
ReactDOM.render( <App />, document.getElementById('root') );
まずindex.htmlのrootがついたdiv要素にrenderメソッドで
constructor(props) { super(props); this.state = {date: new Date()}; }
componentDidMount() { this.timerID = setInterval( () => this.tick(), 1000 ); }
コンポーネントがマウントされたら、1000ミリ秒(1秒)後にtickメソッドを発火させるように指示が出されます。
tick() { this.setState({ date: new Date() }); }
tickメソッドはstateに新しい時間を設定するためのメソッドです。
componentWillUnmount() { clearInterval(this.timerID); }
1000ミリ秒(1秒)後にtickメソッドが発火し、コンポーネントがアンマウントされると走っていたsetIntervalを消します。(これはJavascriptお約束のセットです)
基本的にはcomponentDidMountとcomponentWillUnmountの繰り返しによって、タイマーが作動しているように見えています。