[React講座] Reactエコシステムへの入り口

当ページのリンクには広告が含まれています。
目次

状態管理ライブラリ概説(Redux Toolkit / Zustand など)

なぜ専用ライブラリが必要になるのか?

useState / useReducer / Context だけでも、ある程度までは頑張れますが、規模が大きくなると次のような問題が出てきます:

  • どのコンポーネントが「どの Context」を使っているか分かりにくい
  • 「この画面の state が他のどこから更新されているのか?」の追跡が難しい
  • コンポーネントをまたいだロジック(例:認証情報、カート情報、テーマ設定など)が増えすぎて理解が難しい

そこで登場するのが 状態管理ライブラリ です。
代表的なもの:

  • Redux Toolkit
  • Zustand
  • (他に Recoil, Jotai, MobX など)

ここでは「まずこの2つの性格を押さえる」だけで十分です。

Redux Toolkit(RTK)

位置づけ

  • 「Redux」という古参ライブラリを、現代風に使いやすくラップしたもの
  • いわゆる「グローバルストア型」の代表
  • 「action のログ」「状態の履歴」「開発ツール」の強さが売り

メリット

  • 状態を1か所(store)に集約し、更新の流れが明確
  • Redux DevTools で
    • どの action が dispatch されたか
    • その結果 state がどう変わったか
      を時系列で追える(タイムトラベルも可能)
  • 大規模・チーム開発で「パターンを統一」しやすい

コード例

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

type CounterState = { value: number }

const initialState: CounterState = { value: 0 }

const counterSlice = createSlice({
  name: 'counter',
  initialState,
  reducers: {
    increment(state) {
      state.value += 1
    },
    add(state, action: PayloadAction<number>) {
      state.value += action.payload
    },
  },
})

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

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

export function Counter() {
  const value = useSelector((state: RootState) => state.counter.value)
  const dispatch = useDispatch<AppDispatch>()

  return (
    <div>
      <p>{value}</p>
      <button onClick={() => dispatch(increment())}>+1</button>
    </div>
  )
}

「action を投げる ⇒ reducer が受けて state を変える」という明確な流れがある代わりに、少し儀式的なコードがあります。

Zustand

位置づけ

  • 「必要最低限でいい感じにグローバル state を持ちたい」派
  • Context の拡張版のような軽さ
  • 個人開発・中規模プロジェクトとの相性が良い

メリット

  • APIがシンプルで、カスタムフックっぽく書ける
  • Reduxよりボイラープレートが少ない
  • TypeScriptとの相性も良い

コード例

// useCounterStore.ts
import { create } from 'zustand'

type CounterState = {
  value: number
  increment: () => void
  add: (n: number) => void
}

export const useCounterStore = create<CounterState>((set) => ({
  value: 0,
  increment: () => set((s) => ({ value: s.value + 1 })),
  add: (n) => set((s) => ({ value: s.value + n })),
}))
// Counter.tsx
import { useCounterStore } from './useCounterStore'

export function Counter() {
  const { value, increment } = useCounterStore()
  return (
    <div>
      <p>{value}</p>
      <button onClick={increment}>+1</button>
    </div>
  )
}

見た目はほぼ「useState を外だししただけ」なので、学習コストが低いのが強みです。

どっちを選べばいい?

ざっくりした指針として:

  • まずは Context + useReducer を十分に使いこなす
  • それでもしんどくなってきたら…
    • 状態が極端に多くて、ログをがっつり追いたい
      ⇒ Redux Toolkit
    • そこまで巨大じゃないが、「Contextだとキツい」
      ⇒ Zustand

個人開発なら「Context ⇒ Zustand ⇒ 必要ならRTK」の順が扱いやすいです。

データ取得ライブラリ(React Query / SWR など)

なぜ必要になるのか?

素のReactでAPIを使うと、毎回このパターンを書きがちです:

  • useEffectfetch
  • loading / error / data の3状態を state 管理
  • 再取得(再フェッチ)をしたいときにロジックが複雑になる
  • キャッシュも自前で書く必要あり

同じようなコードを画面ごとにコピペすると、バグも増えるし、挙動の一貫性も失われます。

そこで 「サーバーデータ専用の状態管理ライブラリ」 という考え方が出てきます。

React Query(TanStack Query)

コンセプト

  • useQuery / useMutation というフックを使って、データ取得・更新・キャッシュ・再取得・ローディング・エラー管理を全部任せる ライブラリ

コード例

import { useQuery } from '@tanstack/react-query'
import { fetchTodos } from './api'

export function TodoList() {
  const { data, isLoading, error } = useQuery({
    queryKey: ['todos'],
    queryFn: fetchTodos,
  })

  if (isLoading) return <p>読み込み中...</p>
  if (error) return <p>エラーが発生しました</p>

  return (
    <ul>
      {data.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  )
}

特徴的なポイント:

  • queryKey で「このデータは何か」を識別 ⇒ キャッシュキーになる
  • queryFn が一度成功すると、その結果がキャッシュされる
  • 別コンポーネントで同じ queryKey を使えば、キャッシュを共有できる
  • 「バックグラウンドで新鮮なデータに更新する」など、再取得の戦略も柔軟

「サーバー状態はReact Queryに任せて、ローカル状態だけReactで持つ」という設計にすると、かなり整理されます。

SWR

概要

  • Vercel(Next.jsを作ってる会社)が作ったデータ取得ライブラリ
  • 名前は Stale-While-Revalidate 戦略が由来
    • まずはキャッシュ(stale)を即返す
    • 裏で最新データを取りに行き、終わったら差し替える

コード例

import useSWR from 'swr'
import { fetcher } from './api'

export function UserList() {
  const { data, error, isLoading } = useSWR('/api/users', fetcher)

  if (isLoading) return <p>読み込み中...</p>
  if (error) return <p>エラーが発生しました</p>

  return (
    <ul>
      {data.map((u) => (
        <li key={u.id}>{u.name}</li>
      ))}
    </ul>
  )
}
  • useSWR(key, fetcher) の形で使う
  • React Queryと思想はかなり近い

React Query vs SWR

両方とも優秀なので、ぶっちゃけ どちらでも良い です。
強いて言えば:

  • 強力な機能を網羅的に使いたい ⇒ React Query
  • Next.js + Vercel 文化圏に寄せたい ⇒ SWR

くらいの感覚で覚えておけばOKです。

UIコンポーネントライブラリ(MUI / Chakra UI / Ant Design など)

どんなものか?

「ボタン・フォーム・ダイアログ・テーブル・レイアウトなどを、そこそこ綺麗なデザインで一通り揃えてくれる」 ライブラリです。

メリット:

  • 自前でCSSを書く量を大幅に減らせる
  • コンポーネント単位で一貫したデザインが保てる
  • Formやダイアログ、モーダルなど「めんどいUI」が最初から用意されている

デメリット:

  • デザインがライブラリ色になる(独自ブランドを出しづらい)
  • カスタマイズがやや複雑なこともある
  • バンドルサイズ増加の要因になりうる

MUI(Material UI)

  • Googleの Material Design に準拠
  • コンポーネント数が多く、細かい制御が効く
  • 日本語の情報も多め

コード例:

import Button from '@mui/material/Button'

function App() {
  return <Button variant="contained">送信</Button>
}

「企業っぽい見た目」「管理画面」「ダッシュボード」 にはかなり強いです。

Chakra UI

  • 柔らかいデザインと分かりやすいAPIが特徴
  • Box, Stack などのレイアウトコンポーネントが使いやすい
import { Button, Stack } from '@chakra-ui/react'

function App() {
  return (
    <Stack direction="row" spacing={4}>
      <Button colorScheme="teal">OK</Button>
      <Button variant="outline">キャンセル</Button>
    </Stack>
  )
}

「個人サービスっぽい柔らかいUI」「プロトタイプ」に向いています。

Ant Design

  • 中国発。BtoB向けの業務システム感の強いデザイン
  • テーブルやフォームなど、業務UIに強い印象
import { Button } from 'antd'

function App() {
  return <Button type="primary">送信</Button>
}

「管理画面・ダッシュボード・業務系ツール」をサクッと作るにはかなり強力です。

どう選ぶか?

  • 「自分でデザインしたい・Tailwindなどを使いたい」
    ⇒ UIライブラリは入れず、ヘッドレスUI(Headless UI, Radix UI)+CSSで組む
  • 「とりあえずそれっぽく見せたい」
    ⇒ MUI か Chakra UI のどちらかに乗る
  • 「エンタープライズ系の業務UIを作る」
    ⇒ Ant Design も選択肢

最初の1個としては、MUIかChakraのどちらかを触ってみて「合うほう」を選べばOKです。

Next.jsなどのメタフレームワーク(SSR/SSGの世界)

React単体とNext.jsの違い

React自体は、「コンポーネントを使ってUIを組み立てるためのライブラリ」であって、

  • ルーティング
  • サーバーサイドレンダリング(SSR)
  • 静的サイト生成(SSG)
  • APIサーバー

などは担当外です。

そこをまとめて面倒見てくれるのが Next.js のような「メタフレームワーク」です。

SSR / SSG の概念

  • CSR(Client-Side Rendering)
    • 素のReactでよくあるスタイル
    • ブラウザがJSを読み込んでから画面を描画
  • SSR(Server-Side Rendering)
    • サーバーでHTMLをレンダリングしてからクライアントに返す
    • 初回表示が速くてSEOに強い
  • SSG(Static Site Generation)
    • ビルド時にHTMLを作って、CDNから配信
    • ブログやドキュメントサイトに向く

Next.jsはこれらをページごとに選べるのが強力です。

Next.js のざっくり機能

  • ファイルベースルーティング
    • app/blog/page.tsx みたいなファイルで自動的にルートが決まる
  • サーバーコンポーネント / クライアントコンポーネント
    • 「このコンポーネントはサーバーでレンダする」「これはブラウザ側」などを分けられる
  • API Routes
    • app/api/xxx/route.ts みたいに書いて、簡単なバックエンドを同じプロジェクト内に作れる
  • 画像最適化、Headの管理、レイアウト管理など、Webアプリに必要な周辺を面倒見てくれる

イメージとしては、
React が「エンジン + 車体の一部」
Next.js が「車として走れる状態まで組み上げたフレーム」

という感じです。

おすすめの学習順

  • まずは 素のReactでSPAを1つ作る
    • state, props, hooks, routing の基礎を固める
  • その後、Next.jsに移って
    • SSR / SSG やフルスタック的な構成(簡易API)を学ぶ

いきなりNext.jsから入ることも可能ですが、「React本体の理解」と「Next.jsの仕組み」が頭の中でごちゃっとしやすいので、「React単体で最低1つアプリを作る ⇒ Next.jsへ」という二段構えのほうが、理解は早いです。

まとめ

  • 状態管理ライブラリ
    • Redux Toolkit:大規模向き、履歴・DevToolsが強い
    • Zustand:軽量・シンプル、個人開発や中規模に向く
  • データ取得ライブラリ
    • React Query / SWR:useEffect + fetch の面倒を丸ごと引き受けてくれるサーバー状態管理
    • キャッシュ・再取得・ローディング・エラーを統一的に扱える
  • UIコンポーネントライブラリ
    • MUI / Chakra UI / Ant Design などでボタン・フォーム・ダイアログなどを一気に揃えられる
    • 「自分でCSS書き込むか」「ライブラリに任せるか」の選択
  • メタフレームワーク(Next.js)
    • ルーティング・SSR・SSG・APIなど、Webアプリ全体の構成を引き受けてくれる
    • React単体の次のステップとして「フルスタック寄りの開発」に踏み込める

<<前へ(テストとデバッグ)

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次