ReactJS 関数コンポーネントのライフサイクル:Hooks vs HOC vs Render Props
ReactJS 関数コンポーネント内のライフサイクルメソッド
主要なライフサイクルフック
useState
コンポーネントの状態 (state) を管理するためのフックです。初期値と状態更新関数を返す配列を取得します。
const [count, setCount] = useState(0);
useEffect
副作用処理 (DOM 操作や API 呼び出しなど) を実行するためのフックです。マウント時、更新時、アンマウント時に実行される関数を登録できます。
useEffect(() => {
// DOM 操作
document.title = `Count: ${count}`;
}, [count]);
useMemo
値をキャッシュして再計算を抑制するためのフックです。引数で渡した関数を元に値を生成し、依存関係のリストに基づいて再計算のタイミングを制御します。
const memoizedValue = useMemo(() => {
// 計算コストの高い処理
return expensiveCalculation();
}, [count]);
useRef
DOM 要素やその他の変数を永続的に保持するためのフックです。オブジェクトを生成し、そのプロパティに値を格納できます。
const ref = useRef(null);
useEffect(() => {
// DOM 要素を取得
const element = ref.current;
// ...
}, []);
その他のライフサイクルフック
上記以外にも、useReducer
や useContext
など、様々なライフサイクルフックが存在します。詳細は React 公式ドキュメントを参照してください。
関数コンポーネントでは、クラスコンポーネントのようにライフサイクルメソッドを直接定義することはできません。しかし、フックを使うことで、状態管理、副作用処理、パフォーマンス最適化など、様々なライフサイクルイベントに対応することができます。
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
// タイトル更新
document.title = `Count: ${count}`;
}, [count]);
const ref = useRef(null);
useEffect(() => {
// DOM 要素を取得
const element = ref.current;
if (element) {
element.textContent = count;
}
}, [count]);
const handleClick = () => {
// カウントアップ
setCount(count + 1);
};
return (
<div>
<button onClick={handleClick}>カウントアップ</button>
<span ref={ref}>{count}</span>
</div>
);
}
このコードでは、以下の処理が行われます。
useState
フックを使って、初期値0
の状態変数count
と、その更新関数setCount
を定義します。useEffect
フックを使って、count
の値が更新されるたびに、ドキュメントのタイトルを更新します。useRef
フックを使って、span
要素への参照を取得し、count
の値を表示します。handleClick
関数は、count
の値を 1 増やします。
このコードは、関数コンポーネントでも状態管理、副作用処理、DOM 操作など、様々なライフサイクルイベントに対応できることを示しています。
ReactJS 関数コンポーネント内でライフサイクルメソッドを実装するその他の方法
Higher-Order Components (HOC)
HOC は、コンポーネントに機能を追加するためのラッパーコンポーネントです。ライフサイクルメソッドを追加する HOC を作成することで、その機能を他のコンポーネントに簡単に適用できます。
const withCounter = (Component) => {
const [count, setCount] = useState(0);
useEffect(() => {
// タイトル更新
document.title = `Count: ${count}`;
}, [count]);
const handleClick = () => {
// カウントアップ
setCount(count + 1);
};
return (
<Component count={count} handleClick={handleClick} />
);
};
const App = () => {
return (
<div>
<withCounter>
{({ count, handleClick }) => (
<div>
<button onClick={handleClick}>カウントアップ</button>
<span>{count}</span>
</div>
)}
</withCounter>
</div>
);
};
この例では、withCounter
という HOC を作成し、count
と handleClick
という props をコンポーネントに渡しています。
Render Props は、コンポーネント間でレンダリングロジックを共有するための方法です。ライフサイクルメソッドをラップした Render Props コンポーネントを作成することで、その機能を他のコンポーネントに簡単に適用できます。
const Counter = ({ render }) => {
const [count, setCount] = useState(0);
useEffect(() => {
// タイトル更新
document.title = `Count: ${count}`;
}, [count]);
const handleClick = () => {
// カウントアップ
setCount(count + 1);
};
return render({ count, handleClick });
};
const App = () => {
return (
<div>
<Counter>
{({ count, handleClick }) => (
<div>
<button onClick={handleClick}>カウントアップ</button>
<span>{count}</span>
</div>
)}
</Counter>
</div>
);
};
この例では、Counter
という Render Props コンポーネントを作成し、count
と handleClick
という props を受け取る render 関数を呼び出しています。
Custom Hooks は、独自のライフサイクルロジックをカプセル化するための方法です。他のコンポーネントで再利用可能なフックを作成することで、コードを整理し、DRY (Don't Repeat Yourself) 原則を適用できます。
const useCounter = () => {
const [count, setCount] = useState(0);
useEffect(() => {
// タイトル更新
document.title = `Count: ${count}`;
}, [count]);
const handleClick = () => {
// カウントアップ
setCount(count + 1);
};
return { count, handleClick };
};
const App = () => {
const { count, handleClick } = useCounter();
return (
<div>
<button onClick={handleClick}>カウントアップ</button>
<span>{count}</span>
</div>
);
};
関数コンポーネントで
reactjs redux