ライフサイクル
React 16.3以降、クラスコンポーネントと関数コンポーネントのライフサイクルメソッドには違いがあります。以下では、それぞれのライフサイクルについて説明します。
①クラスコンポーネントのライフサイクル
クラスコンポーネントのライフサイクルは、マウント(Mounting)、更新(Updating)、アンマウント(Unmounting)の3つのフェーズに分かれています。
1.マウント(Mounting)
コンポーネントインスタンスが作成され、DOMに挿入されると、以下のメソッドが順に呼び出されます。
constructor(): コンストラクタ。状態の初期化やイベントハンドラのバインドに使用されます。
static getDerivedStateFromProps(props, state): renderメソッドが呼ばれる前に呼び出され、状態を更新するためのオブジェクトを返すか、状態を更新しない場合はnullを返します。
render(): React要素を返す必要があるメソッド。
componentDidMount(): コンポーネントがマウントされた後に呼び出され、DOM操作やネットワークリクエストに使用されます。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
static getDerivedStateFromProps(props, state) {
// 状態を更新
return null;
}
componentDidMount() {
// コンポーネントがマウントされた後
}
render() {
return <div>{this.state.count}</div>;
}
}
2.更新(Updating)
コンポーネントの状態やプロパティが変化すると、以下のメソッドが順に呼び出されます。
static getDerivedStateFromProps(props, state): 同上。
shouldComponentUpdate(nextProps, nextState): コンポーネントを再レンダリングするかどうかを決定します。trueまたはfalseを返します。
render(): 同上。
getSnapshotBeforeUpdate(prevProps, prevState): 最新のレンダリング出力(DOMノードへのコミット)の直前に呼び出され、返された値はcomponentDidUpdateに渡されます。
componentDidUpdate(prevProps, prevState, snapshot): コンポーネントが更新された後に呼び出されます。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
static getDerivedStateFromProps(props, state) {
return null;
}
shouldComponentUpdate(nextProps, nextState) {
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// コンポーネントが更新された後
}
render() {
return <div>{this.state.count}</div>;
}
}
3.アンマウント(Unmounting)
コンポーネントがDOMから削除されるときに呼び出されるメソッド:
componentWillUnmount(): コンポーネントがアンマウントされる前に呼び出され、リソースのクリーンアップ(例:ネットワークリクエストのキャンセルやイベントリスナーの削除)に使用されます。
class MyComponent extends React.Component {
componentWillUnmount() {
// クリーンアップ作業
}
render() {
return <div>{this.state.count}</div>;
}
}
4.順番について
1.マウントフェーズ(Mounting)
コンポーネントのインスタンスが作成され、DOM に挿入されるとき、マウントフェーズのライフサイクルメソッドは次の順序で実行されます:
constructor()
状態の初期化やメソッドのバインドを行います。
static getDerivedStateFromProps(props, state)
render メソッドが呼ばれる前に呼ばれ、初期化時および更新時の両方で呼ばれます。このメソッドは、状態を更新するオブジェクトを返すか、状態を更新しない場合は null を返します。
render()
必須のメソッドで、レンダリングする React 要素を返します。
componentDidMount()
コンポーネントがマウントされた後(DOM に挿入された後)に直ちに呼ばれます。副作用の操作(例:データの取得、サブスクリプションの設定など)を行うのに適しています。
2.更新フェーズ(Updating)
コンポーネントの props や state が変化したとき、更新フェーズのライフサイクルメソッドは次の順序で実行されます:
static getDerivedStateFromProps(props, state)
マウントフェーズと同様に、render メソッドが呼ばれる前に呼ばれます。
shouldComponentUpdate(nextProps, nextState)
新しい props や state に基づいてコンポーネントの再レンダリングを行うかどうかを決定します。デフォルトは true です。
render()
レンダリングする React 要素を返します。
getSnapshotBeforeUpdate(prevProps, prevState)
最近のレンダリング結果が DOM に反映される直前に呼ばれます。スクロール位置などの情報をキャプチャするために使用されます。このメソッドの戻り値は componentDidUpdate の第3引数として渡されます。
componentDidUpdate(prevProps, prevState, snapshot)
コンポーネントが更新された後に直ちに呼ばれます。DOM 操作や他の副作用の処理を行うのに適しています。
3.アンマウントフェーズ(Unmounting)
コンポーネントが DOM から削除されるとき、アンマウントフェーズのライフサイクルメソッドは次の順序で実行されます:
componentWillUnmount()
コンポーネントがアンマウントされる直前に呼ばれます。このメソッド内でタイマーのクリア、ネットワークリクエストのキャンセル、componentDidMount で作成されたサブスクリプションの解除などのクリーンアップ操作を行います。
4.エラーハンドリング(Error Handling)
レンダリング中、ライフサイクルメソッド内、または任意の子コンポーネントのコンストラクタ内でエラーがスローされた場合、次のメソッドでエラーをキャッチできます:
static getDerivedStateFromError(error)
スローされたエラーに応じて状態を更新するためにレンダリングフェーズ中に呼ばれます。このメソッドは状態を更新するオブジェクトを返すか、状態を更新しない場合は null を返します。
componentDidCatch(error, info)
子コンポーネントでエラーがスローされた後に呼ばれます。このメソッドは、エラーオブジェクトとコンポーネントスタック情報を含むオブジェクトを受け取ります。
②関数コンポーネントのライフサイクル (これは今流行っている構築方法)
関数コンポーネントにはクラスコンポーネントのライフサイクルメソッドはありませんが、React Hooksを使用して同様の機能を実現できます。よく使用されるHookにはuseEffect、useLayoutEffect、useStateなどがあります。
useEffect
useEffectは副作用を処理するためのHookで、データの取得、サブスクリプション、手動でのDOM変更などに使用されます。これはcomponentDidMount、componentDidUpdate、componentWillUnmountの組み合わせとして考えることができます。
import React, { useState, useEffect } from 'react';
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
// componentDidMountとcomponentDidUpdateに相当
console.log('Component mounted or updated');
return () => {
// componentWillUnmountに相当
console.log('Component will unmount');
};
}, [count]); // 依存配列、countが変更されたときに実行
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
export default MyComponent;
useLayoutEffect
useLayoutEffectはuseEffectに似ていますが、すべてのDOM変更の後に同期的に呼び出されます。レイアウトを読み取って同期的に再レンダリングをトリガーする場合に使用されます。使い方はuseEffectと同じです。