useStateとuseEffect、違いを理解していますか?
React開発において、必ず登場するのが useState と useEffect。公式ドキュメントでも最初に紹介され、多くのチュートリアルに登場します。
ですが、こんな疑問を持ったことはありませんか?
-
useEffectって結局いつ動くの?
-
useStateの更新って同期?非同期?
-
useEffectの中でsetStateしていいの?
-
そもそも、何を基準に使い分ければいいの?
これらはReactにおける「状態管理」と「副作用」の違いを正しく理解することで、スッキリ解消できます。
本記事では、useStateとuseEffectの違いと実務での使い分けを、初学者〜中級者向けに丁寧に解説します。
useStateの役割と基本的な使い方とは?
useStateとは?
Reactコンポーネント内で「状態(state)」を持つためのHookです。状態が変わると自動的に再レンダリングが発生します。
import { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>カウント: {count}</p>
<button onClick={() => setCount(count + 1)}>増やす</button>
</div>
);
};
よく使う場面
-
フォームの入力値を保持
-
モーダルの表示/非表示制御
-
フィルター条件やタブの選択状態の管理
useEffectの役割と基本的な使い方とは?
useEffectとは?
Reactの「副作用」を管理するHookです。副作用とは、Reactの外(DOM, API, タイマーなど)とのやり取りを指します。
import { useEffect, useState } from 'react';
const Timer = () => {
const [time, setTime] = useState(0);
useEffect(() => {
const id = setInterval(() => setTime((t) => t + 1), 1000);
return () => clearInterval(id); // クリーンアップ
}, []);
return <p>経過時間: {time}s</p>;
};
よく使う場面
-
初回マウント時にAPIからデータ取得
-
タイマーやイベントリスナーの登録・解除
-
状態変化に応じた外部処理(フェッチ、DOM操作)
状態管理と副作用の関係(図解)
┌────────────┐
│ useState │ ← UIの状態(例: 入力値、カウント)
└────────────┘
│ 状態が変わると
▼
┌────────────┐
│ useEffect │ ← 状態に基づいて副作用を実行(例: 再フェッチ)
└────────────┘
useStateで状態を更新すると、それをトリガーにuseEffectが走る。
この連動関係を理解することが、Reactの挙動を正しく制御する第一歩です。
よくあるつまずきポイントとその回避法
useEffectの依存配列(deps)ミス
useEffect(() => {
fetchUser(userId);
}, [userId]); // ✅ userId変更時に再実行
-
[](空)にすると初回のみ
-
書き忘れると毎回レンダリングで副作用が実行
-
関数を依存に含める場合、useCallbackやuseMemoで安定化しないと無限ループの原因に
useStateの更新は非同期!
setCount(count + 1);
setCount(count + 1); // ❌ → 実際は+1のみ
// ✅ 正しい方法
setCount((prev) => prev + 1);
setCount((prev) => prev + 1); // → 正しく+2になる
状態更新は「バッチ処理」されるため、同じ値に依存するsetStateを連続して使うと意図通り動きません。
ありがちな失敗例とベストプラクティス(API編)
失敗パターン(毎回フェッチ)
const [user, setUser] = useState(null);
const data = fetch('/api/user'); // ❌レンダリングごとに呼ばれる
setUser(data);
正しい書き方
useEffect(() => {
fetch('/api/user')
.then(res => res.json())
.then(data => setUser(data));
}, []); // ✅ 初回だけ実行
ポイント:API通信はuseEffectで制御し、取得データはuseStateに保持。これがReactの基本形です。
useStateとuseEffectの使い分け方まとめ
useStateが適している場面
-
入力値、チェック状態などUI上の可変データ
-
状態変化が画面に即時反映されるもの
useEffectが必要な場面
-
外部との通信や副作用を発生させる処理
-
DOM操作やタイマー、イベントリスナーなど
【設計の指針】迷ったときの判断チャート
この処理、UIの内部だけで完結する?
-
→ Yes → useState
-
→ No(API通信・タイマー・DOM操作など含む)→ useEffect
まとめ|Hooksは「状態」か「副作用」かで使い分けよう
Reactでは、「状態(useState)」と「副作用(useEffect)」の区別が非常に重要です。
使い方をなんとなく理解しているだけでは、意図しない再レンダリングや無限ループの原因になります。
迷ったときは、ぜひこの記事で紹介した原則に立ち返ってみてください。
【外部リンク】
【内部リンク】
【完全版】型の変換とは?キャストの基本と落とし穴」 | Java・JavaScript・TypeScriptで徹底理解する型の扱い方