Skip to content

安全に使えるユースケース

Reactで安全に使えるユースケースと、その理由を詳しく解説します。

useEffectで追加したイベントリスナーやタイマーを、クリーンアップ関数で削除します。

// ✅ 良い例: 適切なクリーンアップ
function Component() {
useEffect(() => {
const handleScroll = () => {
// 処理...
};
window.addEventListener('scroll', handleScroll);
// クリーンアップ関数でイベントリスナーを削除
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
return <div>Component</div>;
}

なぜ安全か:

  • メモリリークの防止: イベントリスナーを明示的に削除し、メモリリークを防止
  • 参照の削除: ハンドラーの参照を削除することで、ガベージコレクションが動作
  • ライフサイクル管理: コンポーネントのライフサイクルに合わせて管理

メモ化による再レンダリングの最適化

Section titled “メモ化による再レンダリングの最適化”

useMemoやuseCallbackを使用して、不要な再レンダリングを防ぎます。

// ✅ 良い例: メモ化による再レンダリングの最適化
function Component({ items }: { items: Item[] }) {
// 計算結果をメモ化
const filteredItems = useMemo(() => {
return items.filter(item => item.active);
}, [items]);
// コールバック関数をメモ化
const handleClick = useCallback((id: number) => {
console.log('Clicked:', id);
}, []);
return (
<div>
{filteredItems.map(item => (
<ChildComponent key={item.id} item={item} onClick={handleClick} />
))}
</div>
);
}
// 子コンポーネントもメモ化
const ChildComponent = React.memo(({ item, onClick }: { item: Item; onClick: (id: number) => void }) => {
return <div onClick={() => onClick(item.id)}>{item.text}</div>;
});

なぜ安全か:

  • 再レンダリングの削減: 不要な再レンダリングを防ぎ、パフォーマンスを向上
  • メモリ使用量の削減: 再レンダリングが削減され、メモリ使用量が削減
  • パフォーマンスの向上: レンダリングパフォーマンスが向上

仮想スクロールによるDOMノード数の制限

Section titled “仮想スクロールによるDOMノード数の制限”

大量のデータを表示する場合、仮想スクロールを使用してDOMノード数を制限します。

// ✅ 良い例: 仮想スクロールによるDOMノード数の制限
import { useVirtualizer } from '@tanstack/react-virtual';
function VirtualList({ items }: { items: Item[] }) {
const parentRef = useRef<HTMLDivElement>(null);
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 50,
overscan: 5, // 表示範囲の前後に5個ずつ余分にレンダリング(スクロール時のちらつき防止)
});
return (
<div ref={parentRef} style={{ height: '500px', overflow: 'auto' }}>
<div
style={{
height: `${virtualizer.getTotalSize()}px`,
width: '100%',
position: 'relative',
}}
>
{virtualizer.getVirtualItems().map(virtualItem => (
<div
key={virtualItem.key}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: `${virtualItem.size}px`,
transform: `translateY(${virtualItem.start}px)`,
}}
>
{items[virtualItem.index].text}
</div>
))}
</div>
</div>
);
}

なぜ安全か:

  • DOMノード数の制限: 表示範囲のアイテムのみをレンダリング(通常10〜20個程度)
  • パフォーマンスの向上: 大量のデータでもレンダリングパフォーマンスが維持される
  • メモリ使用量の削減: 不要なDOMノードを作成しない
  • Reactの最適化: Reactの仮想DOMと組み合わせて、さらに効率的にレンダリング

安全に使えるユースケースのポイント:

  • 適切なクリーンアップ: useEffectで追加したリソースをクリーンアップ関数で削除
  • メモ化による再レンダリングの最適化: useMemoやuseCallbackを使用して不要な再レンダリングを防ぐ
  • 仮想スクロールによるDOMノード数の制限: 大量のデータを表示する場合、仮想スクロールを使用

これらのユースケースを守ることで、安全で信頼性の高いReactアプリケーションを構築できます。