React

パフォーマンス

React

memo・lazy・Suspense・Profiler

React.memo / lazy / Suspense

コンポーネントの遅延読み込みとメモ化

performance.tsx tsx
import { memo, lazy, Suspense } from 'react';

// React.memo: props が変わらなければ再レンダリングをスキップ
const HeavyChart = memo(function HeavyChart({ data, config }) {
    return <canvas>{/* 重い描画処理 */}</canvas>;
});

// カスタム比較関数
const Chart = memo(HeavyChart, (prev, next) => {
    // true を返すと再レンダリングをスキップ
    return prev.data === next.data && prev.config.color === next.config.color;
});

// lazy: コンポーネントを動的インポート(コード分割)
const Dashboard = lazy(() => import('./Dashboard'));
const Settings  = lazy(() => import('./Settings'));

// Suspense: ローディング状態の表示
function App() {
    return (
        <Suspense fallback={<PageSkeleton />}>
            <Dashboard />
        </Suspense>
    );
}

// ルートごとに分割
function Router() {
    return (
        <Suspense fallback={<Spinner />}>
            {route === '/dashboard' && <Dashboard />}
            {route === '/settings'  && <Settings />}
        </Suspense>
    );
}

useTransition / useDeferredValue

UIのブロッキングを防ぐ優先度制御

transitions.tsx tsx
import { useState, useTransition, useDeferredValue } from 'react';

// useTransition: 重い更新を低優先度にする
function SearchPage() {
    const [query,   setQuery]   = useState('');
    const [results, setResults] = useState([]);
    const [isPending, startTransition] = useTransition();

    const handleChange = (e) => {
        setQuery(e.target.value);  // 高優先度(入力は即座に反映)

        startTransition(() => {
            // 低優先度(検索結果の更新は遅延可)
            setResults(heavySearch(e.target.value));
        });
    };

    return (
        <>
            <input value={query} onChange={handleChange} />
            {isPending && <Spinner />}
            <ResultList results={results} />
        </>
    );
}

// useDeferredValue: 値の更新を遅延
function FilteredList({ query }) {
    // query の更新を遅延させて UI をブロックしない
    const deferredQuery = useDeferredValue(query);
    const isStale = query !== deferredQuery;

    return (
        <div style={{ opacity: isStale ? 0.7 : 1 }}>
            <HeavyFilteredList query={deferredQuery} />
        </div>
    );
}