ReactのライフサイクルをChromeのConsoleで確認してみました。
#確認方法
- create-react-appで確認用アプリの雛形を作る
- アプリ内にライフサイクルメソッドを配置し、呼ばれる度に
console.log('【メソッド名】 now!')
を出力する
#扱うメソッド
- constructor()
- render()
- componentDidMount()
- componentDidUpdate()
- shouldComponentUpdate()
- componentWillUnmount()
※「componentWillMount()」などの非推奨とされるメソッドは扱いません
#アプリの作成&起動
> create-react-app LifecycleTest
> cd LifecycleTest
> yarn start
#src/Test.jsを作成
src/Test.jsの中身
import React, { Component } from 'react';
class Test extends Component {
constructor(props) {
super(props);
this.state = {
clicked: false,
}
this.handleClick = this.handleClick.bind(this);
console.log('constructor now!');
}
componentDidMount() {
console.log('componentDidMount now!');
}
handleClick() {
this.setState({
clicked: true,
})
}
componentDidUpdate() {
console.log('componentDidUpdate now!')
}
shouldComponentUpdate() {
console.log('shouldComponentUpdate now!')
return true;
}
render() {
console.log('render now!');
return (
<button onClick={this.handleClick}>Click</button>
);
}
}
export default Test;
#src/App.jsの編集
- 同一階層から、Testコンポーネントをインポート
-
<header></header>
の真下に<Test/>
を配置
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Test from './Test'
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
<Test/>
</div>
);
}
}
export default App;
#Chromeブラウザで確認
ブラウザで起動(同時にマウント)し、Consoleをみると「constructor」→「render」→「componentDidMount」の順でメソッドが呼ばれていることがわかる。
デフォルトのヘッダーの下にあるボタンを押下すると、あらかじめ設定しておいたthis.state.clicked: false
が、this.state.clicked: true
にアップデートされる。
クリックによってアップデートされると、先ほどのマウント時に引き続き「shouldComponentUpdate」→「render」→「componentDidUpdate」の順でメソッドが呼び出されている。
#componentWillUnmountの確認
これまでで
- constructor()
- render()
- componentDidMount()
- componentDidUpdate()
- shouldComponentUpdate()
のライフサイクルが確認できたので、最後に「componentWillUnmount()」を確認します。
#src/App.jsを編集
-
constructor()
を追加 -
handleUnmount()
を追加 -
<button></button>
を配置 -
<Test/>
コンポーネント表示に条件を付加
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Test from './Test'
class App extends Component {
constructor(props) {
super(props);
this.state = {
renderChild: true,
}
this.handleUnmount = this.handleUnmount.bind(this);
}
handleUnmount() {
this.setState({
renderChild: false,
});
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
<button onClick={this.handleUnmount}>Unmount Child</button>
{this.state.renderChild ? <Test number={this.state.number}/> : null}
</div>
);
}
}
export default App;
#src/Test.jsを編集
- src/Test.jsに
componentWillUnmount()
の追加
componentWillUnmount() {
console.log('componentWillUnmount now!')
}
#もう一度ブラウザで確認
再度Chrome上でマウントし、「Click」ボタン→「Unmount Child」ボタンの順に押下することで、このような順序でログが表示される。
#まとめ
- 個人的によく使う「constructor」、「render」、「componentDidMount」あたりの呼び出されるタイミングがミニマムに確認できた
- 「componentWillUnmount」と「shouldComponentUpdate」は初めて使ってみたので、イベントに対する挙動が確認できた