Skip to content

状態管理

公開日:December 10, 2024更新日:December 10, 2024
NextjsTypeScriptCoding📄

この章では、Next.jsアプリケーションにおける状態管理について学びます。状態管理とは、アプリケーション全体で共有されるデータを効率的に管理し、コンポーネント間でデータの受け渡しをスムーズに行うための仕組みです。ここでは、Reactの標準機能であるContext APIと、より高機能な状態管理ライブラリであるZustandの特徴、基本的な使い方、そしてNext.jsアプリケーションへの導入方法を解説します。

1. 状態管理の必要性

小規模なアプリケーションでは、propsのバケツリレー(props drilling)でも状態を管理できるかもしれません。しかし、アプリケーションが大きくなるにつれて、コンポーネントの階層が深くなり、propsだけで状態を管理するのが難しくなります。

状態管理ライブラリを使用すると、アプリケーション全体で共有される状態を一元管理し、どのコンポーネントからでも簡単にアクセスできるようになります。これにより、コードの可読性と保守性が向上し、開発効率がアップします。

2. Context API

Context APIは、Reactに組み込まれている状態管理の仕組みです。特別なライブラリをインストールする必要がなく、手軽に導入できるのが特徴です。

Contextの作成

まずは、状態を保持するためのContextを作成します。createContext関数を使って、新しいContextを作成します。

tsx
// contexts/ThemeContext.tsx

import { createContext, Dispatch, SetStateAction } from 'react';

type Theme = 'light' | 'dark';

type ThemeContextType = {
  theme: Theme;
  setTheme: Dispatch<SetStateAction<Theme>>;
};

const ThemeContext = createContext<ThemeContextType | undefined>(undefined);

export default ThemeContext;

この例では、テーマ(lightまたはdark)を管理するためのThemeContextを作成しています。ThemeContextTypeで、Contextが保持するデータの型を定義しています。

Providerの設定

作成したContextをアプリケーション全体で使えるようにするには、Providerコンポーネントを使って、Contextを適用したいコンポーネントツリーを囲みます。

tsx
// pages/_app.tsx

import { useState } from 'react';
import ThemeContext from '../contexts/ThemeContext';
import type { AppProps } from 'next/app';

function MyApp({ Component, pageProps }: AppProps) {
  const [theme, setTheme] = useState('light');

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      <Component {...pageProps} />
    </ThemeContext.Provider>
  );
}

export default MyApp;

_app.tsxで、ThemeContext.Providerを使ってアプリケーション全体を囲んでいます。value属性に、Contextで共有したいデータを指定します。

Contextの使用

Contextにアクセスするには、useContextフックを使用します。

tsx
// components/ThemeSwitcher.tsx

import { useContext } from 'react';
import ThemeContext from '../contexts/ThemeContext';

const ThemeSwitcher = () => {
  const themeContext = useContext(ThemeContext);

  if (!themeContext) {
    return null;
  }

  const { theme, setTheme } = themeContext;

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };

  return (
    <button onClick={toggleTheme}>
      Switch to {theme === 'light' ? 'dark' : 'light'} mode
    </button>
  );
};

export default ThemeSwitcher;

useContextフックにThemeContextを渡すことで、ThemeContextの値を取得できます。この例では、ボタンをクリックするとテーマが切り替わるコンポーネントを作成しています。

3. Zustand

Zustandは、シンプルで使いやすい状態管理ライブラリです。Context APIよりも高機能で、大規模なアプリケーションの状態管理に適しています。

Zustandのインストール

まず、Zustandをインストールします。

bash
npm install zustand
# または
yarn add zustand
# または
pnpm add zustand

ストアの作成

Zustandでは、状態を管理するためのストアを作成します。create関数を使って、新しいストアを作成します。

tsx
// stores/useCounterStore.ts

import { create } from 'zustand';

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

const useCounterStore = create<CounterState>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}));

export default useCounterStore;

この例では、カウンターの状態を管理するためのuseCounterStoreを作成しています。countという状態と、incrementdecrementという状態を更新するための関数を定義しています。

ストアの使用

ストアにアクセスするには、useCounterStoreフックを使用します。

tsx
// components/Counter.tsx

import useCounterStore from '../stores/useCounterStore';

const Counter = () => {
  const { count, increment, decrement } = useCounterStore();

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
    </div>
  );
};

export default Counter;

useCounterStoreフックを呼び出すだけで、ストアの状態と更新関数を取得できます。この例では、カウントを表示し、+ボタンと-ボタンでカウントを増減できるコンポーネントを作成しています。

4. Context APIとZustandの比較

特徴Context APIZustand
導入のしやすさ組み込み機能なので、インストール不要ライブラリのインストールが必要
学習コスト低いやや高い(ただし、使い方はシンプル)
機能必要最低限の機能を提供高機能(ミドルウェア、開発ツールなど)
パフォーマンス大規模なアプリケーションでは、再レンダリングに注意が必要状態の変更に関連するコンポーネントのみを再レンダリング
適用範囲小規模〜中規模アプリケーション中規模〜大規模アプリケーション

Context APIは、Reactに組み込まれているため、手軽に導入できるのがメリットです。しかし、大規模なアプリケーションでは、パフォーマンスの問題が発生する可能性があります。

Zustandは、シンプルで使いやすいAPIを提供し、パフォーマンスにも優れています。また、ミドルウェアや開発ツールなどの機能も充実しています。

5. その他の状態管理ライブラリ

Context APIとZustand以外にも、状態管理ライブラリはいくつか存在します。

  • Redux: 最も有名な状態管理ライブラリの一つ。大規模アプリケーションでよく使用されるが、学習コストが高く、ボイラープレートが多いというデメリットがある。
  • Recoil: Facebookが開発した状態管理ライブラリ。Reactとの親和性が高く、パフォーマンスにも優れている。
  • Jotai: プリミティブなアプローチで状態を管理するライブラリ。シンプルで使いやすく、パフォーマンスにも優れている。

どの状態管理ライブラリを選ぶかは、アプリケーションの規模や要件、開発チームの好みなどによります。