T-CREATOR

Reactの状態管理2025:「useState」「Redux Toolkit」「Jotai」「Zustand」を比較してみた

Reactの状態管理2025:「useState」「Redux Toolkit」「Jotai」「Zustand」を比較してみた

React開発において、状態管理の選定はアプリケーションの保守性やスケーラビリティを左右する重要な要素です。

2025年現在、さまざまな状態管理ライブラリが登場しており、それぞれに特徴と使いどころがあります。

今回は特に人気と実績のある「useState」「Redux Toolkit」「Jotai」「Zustand」の4つに絞り、実際のコード例を交えながら比較・解説いたします。

※本記事では、Recoilは2025年1月2日にリポジトリがアーカイブされたため、比較対象から除外しております。


最小構成で使えるuseStateの柔軟さ

useStateはReactに組み込まれている最も基本的な状態管理手法です。

追加ライブラリが不要で、小規模な状態であればこれ一つで十分です。

tsximport { useState } from "react";

export function Counter() {
  const [count, setCount] = useState(0);

  return (
    <>
      <p>現在のカウント: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </>
  );
}

特徴と適用範囲

特徴内容
標準機能Reactに標準で組み込まれている
シンプル学習コストが低く、すぐに使える
スケーラビリティ複雑な状態になると管理が煩雑になることがある

公式ドキュメント:useState – React Docs


グローバル管理と非同期処理に強いRedux Toolkit

Reduxは長年使われてきたグローバル状態管理の定番ですが、記述が冗長であるという課題がありました。

その課題を解消したのが公式のRedux Toolkitです。

ts// counterSlice.ts
import { createSlice } from '@reduxjs/toolkit';

export const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: state => {
      state.value += 1;
    },
  },
});

export const { increment } = counterSlice.actions;
export default counterSlice.reducer;
ts// store.ts
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';

export const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
});
tsx// Counter.tsx
import { useSelector, useDispatch } from 'react-redux';
import { increment } from './counterSlice';

export function Counter() {
  const count = useSelector((state: any) => state.counter.value);
  const dispatch = useDispatch();

  return (
    <>
      <p>Redux Count: {count}</p>
      <button onClick={() => dispatch(increment())}>+1</button>
    </>
  );
}

特徴と適用範囲

特徴内容
非同期処理対応createAsyncThunkによるAPI通信の管理が簡潔
DevTools対応Redux DevToolsによるデバッグが可能
分離性store、slice、reducerの役割が明確で大規模でも管理しやすい

公式ドキュメント:Redux Toolkit | Redux


シンプルで直感的なAtomベースのJotai

JotaiはAtomic(原子)状態に基づいた新しい状態管理アプローチを提供します。

必要なデータだけをAtomとして定義でき、スケーラブルでパフォーマンスにも優れています。

ts// atoms.ts
import { atom } from 'jotai';

export const countAtom = atom(0);
tsx// Counter.tsx
import { useAtom } from 'jotai';
import { countAtom } from './atoms';

export function Counter() {
  const [count, setCount] = useAtom(countAtom);

  return (
    <>
      <p>Jotai Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </>
  );
}

特徴と適用範囲

特徴内容
アトム単位管理状態を細かく分割できるため、再レンダリングが最小限で済む
型安全TypeScriptとの親和性が高い
SSR対応React 18以降のStreaming対応も可能

公式ドキュメント:Jotai Documentation


ミニマルでパワフルなZustandの柔軟性

ZustandはReduxのようなFluxアーキテクチャに縛られず、関数型で定義できる状態管理ライブラリです。

コード量が少なく、ボイラープレートが圧倒的に少ないのが魅力です。

ts// useStore.ts
import { create } from 'zustand';

type State = {
  count: number;
  increment: () => void;
};

export const useStore = create<State>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}));
tsx// Counter.tsx
import { useStore } from './useStore';

export function Counter() {
  const { count, increment } = useStore();

  return (
    <>
      <p>Zustand Count: {count}</p>
      <button onClick={increment}>+1</button>
    </>
  );
}

特徴と適用範囲

特徴内容
ボイラープレートなしReduxより簡潔に書ける構文
非同期対応状態ロジック内で直接async関数を利用可能
型の拡張性TypeScriptとの相性も良く、型安全に管理可能

公式ドキュメント:Zustand – Bear necessities for state management


実戦パターン:現場でよく使われる構成例

現場ではライブラリの選定だけでなく、どのように組み合わせて構築するかも重要です。

以下に、各ライブラリが実際にどのような形で導入されているかのパターンを整理いたします。

ライブラリよく使われる構成パターン例
useStateuseEffectと組み合わせたフォーム制御、useReducerと併用して複雑なローカル状態の分離管理
Redux Toolkitslice + thunk + RTK Queryの組み合わせでREST API完全管理、Next.jsとの連携も容易
JotaiProvider + atomFamilyによる動的状態の生成、React Suspenseとの統合による非同期データ制御
Zustandcreate + persist + middlewareで永続化やロギング機能を拡張、特にNext.js・Viteと好相性

たとえばJotaiでは以下のように非同期読み込みを自然に表現できます。

ts// atoms.ts
import { atom } from 'jotai';
import { atomWithQuery } from 'jotai-tanstack-query';

export const userAtom = atomWithQuery(() => ({
  queryKey: ['user'],
  queryFn: () => fetch('/api/user').then(res => res.json()),
}));

パフォーマンス比較:レンダリングと効率性

状態管理ライブラリの選定ではレンダリング最適化も重要なポイントです。

とくに再レンダリングの影響範囲が広いと、ユーザー体験やパフォーマンスに直結します。

ライブラリパフォーマンス特性
useState状態の粒度が小さいため再レンダリング制御は可能だが、共有が困難で冗長になりやすい
Redux Toolkitconnectで最適化できるが、useSelector多用時に再レンダリング範囲が広くなることがある
JotaiAtom単位で依存関係を追跡、再レンダリング範囲が極小。SuspenseやReact.memoとの相性良好
Zustandselectorshallowで再レンダリングを極限まで抑制できる。特にUIの反応性が高い

Zustandでは以下のようにshallowを利用してパフォーマンスを向上させられます。

tsimport { useStore } from './store';
import shallow from 'zustand/shallow';

const Component = () => {
  const [count, increment] = useStore(
    (state) => [state.count, state.increment],
    shallow
  );
};

テストとの親和性:扱いやすさとモックのしやすさ

状態管理はユニットテストやE2Eテストにおける再現性や信頼性にも関係してきます。

それぞれのライブラリのテストしやすさを比較します。

ライブラリテスト観点での評価
useStateローカルな関数単位で完結するためユニットテストが容易
Redux ToolkitStoreやMiddlewareをmockStoreで再現でき、Jestでのテストが体系化されている
JotaiAtomを直接Mockでき、Providerのスコープで状態を制御しやすい
ZustandStoreを直接差し替え可能。状態の初期化や書き換えも柔軟でテストシナリオ構築が簡単

Zustandのテスト例:

tsimport { useStore } from './store';

beforeEach(() => {
  useStore.setState({ count: 100 });
});

it('初期状態が正しく設定されているか', () => {
  expect(useStore.getState().count).toBe(100);
});

Redux ToolkitではMockStoreを使った統一的なテストが可能です。

tsimport configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

it('アクションが正しくディスパッチされるか', () => {
  const store = mockStore({ counter: { value: 0 } });
  store.dispatch(increment());
  const actions = store.getActions();
  expect(actions[0].type).toBe('counter/increment');
});

補足:公式ドキュメントリンクまとめ

ライブラリリンク
useStatehttps://react.dev/reference/react/useState
Redux Toolkithttps://redux-toolkit.js.org/
Jotaihttps://jotai.org/
Zustandhttps://zustand-demo.pmnd.rs/

まとめ

2025年現在、Reactの状態管理には多彩な選択肢が存在しております。

それぞれに向き・不向きがあり、以下の観点から適切なライブラリを選択することが重要です。

状態管理ライブラリ選定の5つの視点

観点チェックポイント例
状態のスコープ局所的な状態か、アプリ全体で共有すべきグローバル状態か
非同期処理の必要性APIとのやりとりをどのように扱うか、thunkやsuspenseなどが必要か
プロジェクトの規模小規模ならuseState、中〜大規模ならRedux ToolkitZustandが適する
パフォーマンス効率再レンダリングを最小限に抑えたいならJotaiZustandが非常に有効
テストのしやすさ状態のMockや再現性の高いテストを重視するならRedux ToolkitZustandが柔軟に対応可能

状態管理ライブラリ早見表

ライブラリスコープ非同期実戦パターンパフォーマンステストのしやすさ
useStateローカルuseReducer併用の局所構成良(粒度次第)非常に良い
Redux Toolkitグローバルslice + thunk + RTK Queryによる構造的構成中(最適化次第)モック・DevTools対応
Jotai柔軟atomFamily + Suspenseによる非同期制御非常に良いProviderで切替可能
Zustandグローバルcreate + persist + middleware構成が人気非常に良い柔軟な状態初期化可

結論としては、以下のように選ぶと良いでしょう:

  • 小規模・シンプルなアプリ:useStateuseReducerで十分
  • 非同期処理が中心:Redux ToolkitJotai
  • パフォーマンス最優先:ZustandJotai
  • テスト重視・エンタープライズ対応:Redux ToolkitZustand
  • 柔軟な開発体験を求める:ZustandJotaiが直感的でおすすめ

今後もReactエコシステムの進化に合わせ、最適な状態管理戦略を選び続けることが、プロダクトの品質と開発体験を高める鍵となります。

本記事が、皆さまの状態管理選定と実装において、少しでも参考になれば幸いです。

記事Article

もっと見る