Reactライフサイクルを学ぶ実践アプリ例!初心者でもわかるReactライフサイクル解説
生徒
「Reactのライフサイクルって、実際にどんなアプリで学べますか?」
先生
「簡単なカウンターやタイマーのアプリを作ると、レンダリングや副作用、アンマウントなどライフサイクルの動きがよくわかります。」
生徒
「具体的にどんなコードを書けばいいですか?」
先生
「それでは、カウンターアプリを例に見ていきましょう!」
1. カウンターアプリでライフサイクルを学ぶ
まずはカウンターアプリを作ります。このアプリではボタンを押すとカウントが増え、画面に表示されます。useStateで状態管理を行い、useEffectで副作用を扱います。
import React, { useState, useEffect } from "react";
function CounterApp() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("カウンターがレンダリングされました:", count);
return () => {
console.log("コンポーネントがアンマウントまたは更新されます:", count);
};
}, [count]);
return (
<div>
<h1>カウント: {count}</h1>
<button onClick={() => setCount(count + 1)}>カウントを増やす</button>
</div>
);
}
export default CounterApp;
2. タイマーアプリで副作用とアンマウントを理解する
次にタイマーアプリを作ります。useEffectでタイマーを設定し、アンマウント時にクリーンアップすることで、メモリリークを防ぎます。これでライフサイクルの重要な部分を学べます。
import React, { useState, useEffect } from "react";
function TimerApp() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);
return () => clearInterval(interval); // アンマウント時にクリーンアップ
}, []);
return <h1>経過秒数: {seconds}</h1>;
}
export default TimerApp;
3. useLayoutEffectで画面表示のタイミングを確認
useLayoutEffectはDOMが描画される直前に実行されるため、画面表示に影響する処理を正確に行えます。例えば、要素のサイズを取得して位置を調整する場合に使います。
import React, { useState, useLayoutEffect, useRef } from "react";
function LayoutEffectApp() {
const [width, setWidth] = useState(0);
const divRef = useRef();
useLayoutEffect(() => {
setWidth(divRef.current.offsetWidth);
}, []);
return (
<div>
<div ref={divRef} style={{ width: "50%" }}>幅を測定</div>
<p>測定した幅: {width}px</p>
</div>
);
}
export default LayoutEffectApp;
4. 実践アプリで学ぶポイント
これらのアプリを作ることで、Reactのライフサイクルの理解が深まります。状態の更新、レンダリング、副作用、クリーンアップ、DOM操作のタイミングなど、実際に手を動かして確認することが大切です。
特に初めてReactを学ぶ場合は、console.logを活用してレンダリングや副作用のタイミングを目で確認する方法がおすすめです。
5. 応用アイデア
カウンターやタイマーアプリに、データフェッチやフォーム、リスト操作などを組み合わせることで、より複雑なライフサイクルの管理も学べます。useEffectやuseLayoutEffectの使い分け、状態管理、クリーンアップの重要性を理解する絶好の練習になります。
まとめ
今回の記事では、Reactのライフサイクルを具体的に理解するために、カウンターアプリ、タイマーアプリ、そして描画タイミングを制御するレイアウト調整アプリの3つを例に解説してきました。Reactの開発において、コンポーネントがいつ生まれ(マウント)、いつ更新され(アップデート)、そしていつ消えるのか(アンマウント)という流れを把握することは、バグの少ない高品質なアプリケーションを作るための第一歩です。
特に「useEffect」は、現代のReact開発(関数コンポーネント)において最も重要なフックの一つです。APIからのデータ取得やイベントリスナーの登録、そして忘れがちな「クリーンアップ処理(後片付け)」といった一連の動作を、ライフサイクルに沿って適切に記述するスキルが求められます。また、画面がガタつくのを防ぎたい場合には「useLayoutEffect」を検討するなど、状況に応じた使い分けも重要です。
さらに理解を深めるための実践コード:データフェッチとライフサイクル
実際の現場でよく使われる、外部APIからデータを取得する際のライフサイクル管理についても触れておきましょう。ここでは、コンポーネントがマウントされた瞬間に一度だけデータを取得し、画面を更新するサンプルを紹介します。
import React, { useState, useEffect } from "react";
function UserListApp() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
// コンポーネントのマウント時に実行される
const fetchUsers = async () => {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
const data = await response.json();
setUsers(data);
setLoading(false);
} catch (error) {
console.error("データの取得に失敗しました:", error);
setLoading(false);
}
};
fetchUsers();
// 依存配列を空にすることで、初回レンダリング時のみ実行される
}, []);
if (loading) return <p>読み込み中...</p>;
return (
<div>
<h3>ユーザーリスト</h3>
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
export default UserListApp;
このように、ライフサイクルを意識することで「いつ通信を開始し、いつ画面を更新するか」を意図通りにコントロールできるようになります。Reactの学習は、まず基本の型を覚え、次に今回紹介したようなコードを自分で書き換えて、ブラウザのコンソールでログを確認しながら進めるのが一番の近道です。
また、最新のReact(バージョン18以降)では、開発モードでuseEffectが2回実行される仕様があるため、一見すると挙動がおかしく感じることもあるかもしれません。しかし、これはクリーンアップ処理が正しく実装されているかを検証するための重要な仕組みです。エラーが出たからと焦るのではなく、しっかりとコンポーネントの「一生」を見守る意識でコードを書いてみてください。
生徒
「先生、今回のタイマーやカウンターの例を見て、ようやくuseEffectの第二引数の意味が分かりました!空の配列にすると一度だけ動いて、変数を入れるとその変数が変わったときだけ動くんですね。」
先生
「その通りです。それがマウント時とアップデート時のライフサイクルの制御になります。特にタイマーの例で紹介した『クリーンアップ(return句)』は理解できましたか?」
生徒
「はい!clearIntervalを書かないと、コンポーネントが画面から消えても裏でずっとタイマーが動き続けてしまうんですよね。これがメモリリークの原因になるって聞いて、ちょっと怖くなりました(笑)」
先生
「ははは、そうですね。でもその『怖さ』を知っているだけで、エンジニアとしては一歩前進ですよ。後片付けを忘れない習慣がつけば、複雑なアプリでも動作が重くならずに済みます。」
生徒
「あと、useLayoutEffectについても少し驚きました。useEffectと見た目は似ているけど、動くタイミングがわずかに違うだけで、画面のチラつきを防げるんですね。」
先生
「鋭いですね。ブラウザが実際に画面を塗り替える前に処理を挟めるのが強みです。基本はuseEffectでいいですが、UIの微調整が必要なときは頼りになる存在ですよ。」
生徒
「なるほど。まずはuseEffectをしっかり使いこなせるように練習して、次はAPI連携などのもっと実践的なプログラムに挑戦してみます!」
先生
「素晴らしい意気込みです。ライフサイクルをマスターすれば、Reactがぐっと楽しくなりますよ。ぜひこの調子で頑張りましょう!」