React パフォーマンス最適化の完全ガイド【2026年版】useMemo・useCallback・React.memo・Suspenseを使いこなす

Reactアプリが遅くなる原因と最適化の考え方

Reactアプリケーションが大きくなるにつれて、パフォーマンスの問題が顕在化してきます。主な原因は不要な再レンダリング重い計算処理です。この記事では、Reactのパフォーマンス最適化テクニックを体系的に解説します。

Reactのレンダリングの仕組み

Reactは以下のいずれかの条件で再レンダリングが発生します。

  • コンポーネントのstateが変化した時
  • コンポーネントのpropsが変化した時
  • 親コンポーネントが再レンダリングされた時
  • useContextのcontextが変化した時

React.memoでコンポーネントのメモ化

import React, { memo } from 'react';

// メモ化なし:親が再レンダリングされるたびに再レンダリング
function ExpensiveComponent({ data, onUpdate }) {
  console.log('レンダリング実行');
  return <div>{data.name}</div>;
}

// React.memoでメモ化:propsが変わらない限り再レンダリングしない
const MemoizedComponent = memo(function ExpensiveComponent({ data, onUpdate }) {
  console.log('レンダリング実行');
  return <div>{data.name}</div>;
});

// カスタム比較関数(深い比較が必要な場合)
const MemoWithCustomCompare = memo(
  ExpensiveComponent,
  (prevProps, nextProps) => {
    return prevProps.data.id === nextProps.data.id &&
           prevProps.data.name === nextProps.data.name;
  }
);

useMemoで計算結果をメモ化

import { useMemo, useState } from 'react';

function ProductList({ products, filterText, sortBy }) {
  // filterTextかsortByが変わった時だけ再計算
  const filteredAndSortedProducts = useMemo(() => {
    console.log('フィルタリング・ソート処理実行');
    return products
      .filter(p => p.name.toLowerCase().includes(filterText.toLowerCase()))
      .sort((a, b) => {
        if (sortBy === 'price') return a.price - b.price;
        if (sortBy === 'name') return a.name.localeCompare(b.name);
        return 0;
      });
  }, [products, filterText, sortBy]);

  return (
    <ul>
      {filteredAndSortedProducts.map(p => (
        <li key={p.id}>{p.name}: ¥{p.price.toLocaleString()}</li>
      ))}
    </ul>
  );
}

useCallbackで関数をメモ化

import { useCallback, useState } from 'react';

function ParentComponent() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');

  // countが変わってもhandleClickは同じ関数オブジェクトを返す
  // → MemoizedChildは不要な再レンダリングをしない
  const handleClick = useCallback((id) => {
    console.log('クリック:', id);
    // 最新のstateが必要な場合は関数形式で更新
    setCount(prev => prev + 1);
  }, []); // 依存関係なし

  return (
    <div>
      <p>Count: {count}</p>
      <input value={text} onChange={e => setText(e.target.value)} />
      <MemoizedChild onClick={handleClick} />
    </div>
  );
}

Code Splitting と遅延読み込み

import React, { lazy, Suspense } from 'react';
import { Routes, Route } from 'react-router-dom';

// 重いコンポーネントを遅延読み込み
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Analytics = lazy(() => import('./pages/Analytics'));
const Settings = lazy(() => import('./pages/Settings'));

function App() {
  return (
    <Suspense fallback={<div className="loading">読み込み中...</div>}>
      <Routes>
        <Route path="/" element={<Dashboard />} />
        <Route path="/analytics" element={<Analytics />} />
        <Route path="/settings" element={<Settings />} />
      </Routes>
    </Suspense>
  );
}

仮想スクロールで大量データを処理

import { FixedSizeList as List } from 'react-window';

// 10万件のデータでも軽快に表示
function VirtualizedList({ items }) {
  const Row = ({ index, style }) => (
    <div style={style}>
      {items[index].name}: {items[index].value}
    </div>
  );

  return (
    <List
      height={500}    // 表示エリアの高さ
      itemCount={items.length}
      itemSize={35}   // 各行の高さ
      width="100%"
    >
      {Row}
    </List>
  );
}

React DevToolsでパフォーマンスを計測する

React DevToolsのProfilerタブを使って、どのコンポーネントが遅いかを特定できます。

  1. ChromeにReact Developer Toolsをインストール
  2. DevToolsを開き「Profiler」タブを選択
  3. 「録画開始」ボタンを押して操作を行う
  4. 「録画停止」で結果を分析
  5. 「Flamegraph」で各コンポーネントのレンダリング時間を確認

パフォーマンス最適化のベストプラクティス

テクニック 使いどころ 効果
React.memo propsが変わりにくいコンポーネント 不要な再レンダリングを防止
useMemo 重い計算処理 計算結果をキャッシュ
useCallback 子コンポーネントに渡す関数 関数オブジェクトの再生成を防止
lazy/Suspense 大きなコンポーネント 初期読み込み時間を短縮
仮想スクロール 長大なリスト DOM要素数を削減

まとめ

  • ✅ まずはDevToolsで問題箇所を特定する
  • ✅ React.memo・useMemo・useCallbackを適切に使用
  • ✅ Code Splittingで初期ロード時間を短縮
  • ✅ 大量データにはreact-windowの仮想スクロールを活用

過剰な最適化は逆効果になることもあります。まずProfilerで計測し、本当にボトルネックになっている箇所だけを最適化しましょう。

投稿者 kasata

IT企業でエンジニアとして勤務後、テクノロジー情報メディア「Tech Athletes(テック・アスリート)」を運営。プログラミング、クラウドインフラ(AWS/GCP/Azure)、AI活用、Webサービス開発を専門とする。エンジニア・ビジネスパーソン向けに、実際に使ってみた経験をもとに信頼できる技術情報を発信中。資格:AWS認定ソリューションアーキテクト、Python 3 エンジニア認定試験合格。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です