第2回の今回はReactのコンポーネントの次に重要となるフックについて解説します。
記事見出し一覧
-
第1回【React】:React入門 — コンポーネントとJSXの基本
- Reactとは何か、コンポーネントについて学ぶ
-
第2回【React】:フック入門 — useState と useEffect
- useState と useEffectというReactの関数を学ぶ
-
第3回【React】:コンポーネント間で値を共有する方法
- 複数のコンポーネントを作ったときの値の共有方法を学ぶ
-
第4回【Next.js】:Next.jsの基本
- Next.jsとは、ルーティングについて学ぶ
-
第5回【Next.js】:(補足)サーバーコンポーネントとクライアントコンポーネント
- サーバーコンポーネントとクライアントコンポーネントについて学ぶ
第2回:フック入門 — useState と useEffect
フックとは
簡単に言えばReactのコンポーネントに関する関数
その中でも最低限覚えておくべきuseStateとuseEffectを紹介していきます。
(参考)フックの一覧
useStateの使い方
useStateはstateという名前の通り「状態」を持つ変数と関数のセットのことです。
useStateを使ったコードは下記のようになります。
React公式ページを参考に作ったカウンター
このコードではボタンを押すとカウントアップされるカウンターを作っています。
カウント数をcount変数で持っていますが、useStateでカウント数を持っていることでコンポーネント内の表示値が変わって描画されます。
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>カウント: {count}</p>
<button onClick={() => setCount(count + 1)}>
増やす
</button>
</div>
);
}
解説
useStateの使い方:
import { useState } from 'react';をしたうえで
const [状態変数, 更新関数] = useState(初期値); という構文で宣言します。
const [count, setCount] = useState(0);という文ではcountという変数で参照し、setCount()という関数でcountという変数を更新し、countの初期値は0という数値で定義しています。
命名規則について
状態変数と更新関数の命名は自由ですが、慣習として以下のパターンが推奨されています:
- 状態変数:
hoge(なんでもよい) - 更新関数:
setHoge(状態変数の先頭にsetを付けて1文字目を大文字にする)
変数ではなくなぜuseStateを使うのか
値(状態)を保持するだけであれば変数でもいいはずだが、なぜuseStateを使うのかというとコンポーネントの再描画に関わってくるためです。
Reactでは更新されたものだけコンポーネントを再描画させるという仕様があり、画面をリロードすることなく効率よく描画内容を変えているのですが、
変数の値が変更されただけでは再描画はされず、useStateの値が変わった場合に更新を検知し、その値を使っているコンポーネントを再描画するという仕様になっています。
useStateを使うことで、Reactは「どの値が変わったか」を追跡でき、 必要な部分だけを再描画できるようになります。 もし普通の変数を使った場合、Reactは値の変更を検知できないため画面が更新されません。
useEffectの使い方
useEffectとは
画面表示以外の処理(**副作用(エフェクト)**と呼ぶ)をどのタイミングで実行するかを制御する関数です。
副作用の例:
- APIでニュースを取得する
- DBからデータを取得する
- タイマーを開始する
例えば「ページを開いた後に、自動でニュースをAPIから取得する」といった場合のAPIからの取得処理を、useEffectでどのタイミングで取得するのかを制御できます。
実行タイミング
処理(エフェクト)の実行タイミングとしては以下が設定可能
① 最初の1回だけ実行
- 最初に画面が表示されたときのみ(最初の1回だけ実行)
useEffect(() => {
// 処理
}, []); // 空配列
② 特定の値が変わったときだけ実行
- 特定の変数の値が変わったときだけ実行
useEffect(() => {
// 処理
}, [count, userId]); // 監視する値を配列で指定
この配列を依存配列と呼びます。countやuserIdが変更されたときのみ、useEffect内の処理が実行されます。
③ 再描画されるたびに毎回実行
- 自身のコンポーネントが再描画された際に毎回実行
useEffect(() => {
// 処理
}); // 依存配列なし
注意:
親コンポーネントが再描画されると、デフォルトでは子コンポーネントも再描画されるため、結果的にuseEffectも実行されます。
特に依存配列なし(③)でuseStateを更新すると「再描画する→useEffectが実行される→再描画する→...」の無限ループに陥りやすいので注意。
useEffectを使ったコード例:タイマー
コンポーネントが表示された初回にタイマーを起動。画面を遷移したり、タイマー自体を非表示にしたりコンポーネントが画面から消えたときにクリーンアップ関数が動き、タイマーが停止する。
ここでのエフェクト:タイマーのカウント処理
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
// タイマーを開始
const intervalId = setInterval(() => {
setSeconds(prev => prev + 1);
}, 1000);
// クリーンアップ関数(コンポーネントが消えるときに実行される)
return () => {
clearInterval(intervalId); // タイマーを停止
console.log('タイマーを停止しました');
};
}, []); // 最初の1回だけ実行
return <p>経過時間: {seconds}秒</p>;
}
useEffectを使ったコード例
タイマー
ストップウォッチ
カウンター(useEffect使用)
クリーンアップ関数
useEffectの戻り値でクローズ処理など、useEffect内で行う処理が実行された後に行う後始末をreturn文内に書く
上記のコードでは下記がuseEffectのクリーンアップ関数で、コンポーネントが画面から消えるときにタイマーを停止する。
例えばストップウォッチの表示ページから別ページへ移動して、ストップウォッチのコンポーネントが表示されなくなってもタイマーが動き続けることを防ぐ。
// クリーンアップ関数(コンポーネントが消えるときに実行される)
return () => {
clearInterval(intervalId); // タイマーを停止
console.log('タイマーを停止しました');
};
エフェクト(副作用)とは
画面表示以外の処理のこと(APIの呼び出し、タイマー処理でのカウントなど)
エフェクト(処理)の実行タイミングをuseEffectという関数で制御している。
次回
次回はReactの複数のコンポーネントを作ったときの値の共有方法を学びます。
第3回へ