Loading
  • LIGHT

  • DARK

ROUTE

ルートゼロの
アクティビティ

【保存版】ReactのuseStateとuseEffectの違いとは?初心者が実務で迷わない使い分け完全ガイド

9

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)」の区別が非常に重要です。

使い方をなんとなく理解しているだけでは、意図しない再レンダリングや無限ループの原因になります。

迷ったときは、ぜひこの記事で紹介した原則に立ち返ってみてください。

【外部リンク】

React公式: useStateの解説

React公式: useEffectの解説

MDN: Promise

MDN: Fetch API

【内部リンク】

【完全版】型の変換とは?キャストの基本と落とし穴」 | Java・JavaScript・TypeScriptで徹底理解する型の扱い方

非同期処理の基本を理解|setTimeout・Promise・async/awaitの違いと使い方

RANKINGranking-icon

LATEST POSTS

もっとルートゼロを知りたいなら

DISCOVER MORE