---
title: "Reactで複数選択比較機能を実装する方法|useStateとアクセシビリティ対応完全ガイド"
description: "Reactで複数選択比較機能を実装する方法を徹底解説。useStateを使った選択状態管理、Setと配列の組み合わせパターン、モーダルのアクセシビリティ(フォーカストラップ)対応まで、実践的なコード例と共に紹介します。"
created: "2026-01-01"
status: "draft"
platforms:
wordpress:
published: false
url: ""
published_date: ""
category: "react-nextjs/ui"
tags:
- "React Hooks"
- "useState"
- "複数選択"
- "モーダル"
- "状態管理"
- "アクセシビリティ"
- "フォーカストラップ"
---

## はじめに:Reactで複数選択比較機能を実装する方法
お気に入り一覧ページに「複数のアイテムを横並びで比較する機能」が必要になりました。
ユーザーが2〜4個のアイテムを選択し、価格・サービス・営業時間などの情報を一覧で比較できるモーダル形式のUIを実装しました。
本記事では、**Reactで複数選択機能を実装する方法**について、実際のコード例を交えながら詳しく解説します。
具体的には以下のトピックをカバーします。
- useStateを使った選択状態管理のベストプラクティス
- Setと配列を組み合わせた高速な選択パターン
- Prune Logicによる外部状態との同期方法
- モーダルのアクセシビリティ対応(フォーカストラップ、スクロールロック)
- 実践的なテスト戦略
## こんな人におすすめ
- **Reactで複数選択機能**を実装したい方
- useStateを使った**選択状態管理**のベストプラクティスを知りたい方
- **Reactモーダル**のアクセシビリティ対応(フォーカストラップ)に関心がある方
- **Prune Logic**(外部状態との同期)を実装したい方
- 比較機能やテーブル表示を実装する際の設計パターンを学びたい方
## 目次
- [はじめに:Reactで複数選択比較機能を実装する方法](#はじめにreactで複数選択比較機能を実装する方法)
- [こんな人におすすめ](#こんな人におすすめ)
- [React比較機能の要件定義](#react比較機能の要件定義)
- [Reactでの実装方針:useStateと型定義](#reactでの実装方針usestateと型定義)
- [1. 型定義と定数](#1-型定義と定数srctypescomparets)
- [2. useStateで複数選択状態を管理する方法](#2-usestateで複数選択状態を管理する方法)
- [3. Prune Logic:外部状態と選択状態の同期方法](#3-prune-logic外部状態と選択状態の同期方法)
- [4. Reactモーダルのアクセシビリティ対応](#4-reactモーダルのアクセシビリティ対応)
- [5. 比較データの差異ハイライト実装](#5-比較データの差異ハイライト実装)
- [ポイント](#ポイント)
- [選択順の保持](#選択順の保持)
- [イベント伝播の制御](#イベント伝播の制御アイテムカード)
- [データフォールバック](#データフォールバック)
- [学び](#学び)
- [1. 選択状態の管理パターン](#1-選択状態の管理パターン)
- [2. Prune Logicの重要性](#2-prune-logicの重要性)
- [3. メタデータ駆動設計](#3-メタデータ駆動設計)
- [4. モーダルのアクセシビリティ](#4-モーダルのアクセシビリティ)
- [テスト戦略](#テスト戦略)
- [よくある質問:React複数選択機能の実装について](#よくある質問react複数選択機能の実装について)
- [Q1: Reactで複数選択機能を実装する最も簡単な方法は?](#q1-reactで複数選択機能を実装する最も簡単な方法は)
- [Q2: useStateで選択状態を管理する際のパフォーマンスは?](#q2-usestateで選択状態を管理する際のパフォーマンスは)
- [Q3: モーダルのフォーカストラップとは何ですか?](#q3-モーダルのフォーカストラップとは何ですか)
- [Q4: Prune Logicとはどういう意味ですか?](#q4-prune-logicとはどういう意味ですか)
- [Q5: Reactモーダル実装でよくあるバグは?](#q5-reactモーダル実装でよくあるバグは)
- [まとめ:React複数選択比較機能の実装ガイド](#まとめreact複数選択比較機能の実装ガイド)
## React比較機能の要件定義
実装する比較機能の要件を整理します。
- 比較モードのON/OFF切り替えができること
- 2〜4個のアイテムを選択可能(選択順で表示)
- モーダル形式で横並び比較テーブルを表示
- アイテム間で値が異なる行を黄色背景でハイライト
- お気に入り解除時に選択状態を自動同期(prune logic)
- フォーカストラップ+スクロールロック対応
- ESCキー、オーバーレイクリック、閉じるボタンで閉じます
```mermaid
stateDiagram-v2
[*] --> 通常モード
通常モード --> 比較モード: トグルON
比較モード --> 通常モード: トグルOFF
比較モード --> 比較テーブル表示: 2社以上選択
比較テーブル表示 --> 比較モード: 選択数が2社未満
比較テーブル表示 --> 通常モード: 閉じる操作
note right of 比較モード
最大4社まで選択可能
選択順を保持
end note
```
## Reactでの実装方針:useStateと型定義
### 1. 型定義と定数(`src/types/compare.ts`)
```typescript
export const MAX_COMPARE_SELECTION = 4;
export const MIN_COMPARE_SELECTION = 2;
export interface CompareField {
key: string;
label: string;
icon?: string;
getValue: (company: Company) => string | string[];
getNormalizedValue: (company: Company) => string;
}
export const COMPARE_FIELDS: CompareField[] = [
{ key: 'unitPrice', label: '単価', /* ... */ },
{ key: 'wasteTypes', label: '対応廃棄物', /* ... */ },
// ...
];
```
比較項目をメタデータ駆動で定義。拡張性を確保。
### 2. useStateで複数選択状態を管理する方法
```typescript
const [isCompareMode, setIsCompareMode] = React.useState(false);
const [selectedForCompare, setSelectedForCompare] = React.useState<Set<string>>(new Set());
const [selectedOrder, setSelectedOrder] = React.useState<string[]>([]);
const [showCompareTable, setShowCompareTable] = React.useState(false);
```
- `Set` で選択状態を管理します(O(1)の存在チェック)
- 配列で選択順を保持します(表示順を制御)
```mermaid
graph LR
A[Set<string>] -->|高速検索 O1| B[選択状態管理]
C[string配列] -->|順序保持| D[表示順制御]
B --> E[選択操作]
D --> E
style A fill:#e1f5fe
style C fill:#fff3e0
style E fill:#c8e6c9
```
### 3. Prune Logic:外部状態と選択状態の同期方法
```typescript
React.useEffect(() => {
setSelectedForCompare(prev => {
const pruned = new Set([...prev].filter(id => bookmarkedIds.has(id)));
if (pruned.size < MIN_COMPARE_SELECTION && showCompareTable) {
setShowCompareTable(false);
}
return pruned;
});
setSelectedOrder(prev => prev.filter(id => bookmarkedIds.has(id)));
}, [bookmarkedIds, showCompareTable]);
```
お気に入りアイテムが削除されたら、選択状態から自動的に除外します。最小選択数を下回ったら比較テーブルを閉じます。
**Prune Logic**とは、外部状態(お気に入り)が変化した際に、依存する状態(選択)を自動的に同期するパターンです。
```mermaid
flowchart TD
A[お気に入り削除] --> B{選択状態に含まれる?}
B -->|はい| C[選択状態から除外]
B -->|いいえ| D[何もしない]
C --> E{選択数 < 2?}
E -->|はい| F[比較テーブルを閉じる]
E -->|いいえ| G[表示を維持]
style A fill:#ffcdd2
style F fill:#fff9c4
style G fill:#c8e6c9
```
### 4. Reactモーダルのアクセシビリティ対応
**アクセシビリティ対応**はモーダル実装で最も重要な要素です。
- **フォーカストラップ**: キーボードユーザーがTabキーで操作する際、フォーカスがモーダル外に逃げないようにする機能
- **スクロールロック**: `body` に `overflow: hidden` を適用
- **ESCキー対応**: `keydown` イベントで閉じる処理
※ フォーカストラップの詳細な実装方法は、後述の「Q3: モーダルのフォーカストラップとは何ですか?」で解説しています。
### 5. 比較データの差異ハイライト実装
```typescript
export function hasValueDifference(
companies: Company[],
field: CompareField
): boolean {
const normalizedValues = companies.map(field.getNormalizedValue);
const uniqueValues = new Set(normalizedValues);
return uniqueValues.size > 1;
}
```
正規化した値で比較します。1つでも異なる値があれば `true` です。
## ポイント
### 選択順の保持
```typescript
const handleToggleCompareSelection = (companyId: string) => {
setSelectedForCompare(prev => {
const newSet = new Set(prev);
if (newSet.has(companyId)) {
newSet.delete(companyId);
setSelectedOrder(order => order.filter(id => id !== companyId));
} else if (newSet.size < MAX_COMPARE_SELECTION) {
newSet.add(companyId);
setSelectedOrder(order => [...order, companyId]);
}
return newSet;
});
};
```
`Set` と配列を同時に更新します。Setで高速検索、配列で順序を保証します。
### イベント伝播の制御(アイテムカード)
比較モード時はカードクリックで選択切替、通常モードは詳細モーダル表示します。
```typescript
const handleCardClick = () => {
if (isCompareMode) {
if (!isSelectionDisabled || isSelectedForCompare) {
onToggleCompareSelection?.();
}
} else {
onCardClick();
}
};
```
お気に入り解除ボタンは `stopPropagation()` でカードクリックに影響しないようにします。
### データフォールバック
```typescript
const operatingHours = company.operatingHours ||
(company.businessHours ? `平日: ${company.businessHours}` : '情報なし');
```
`operatingHours` が空なら `businessHours` から生成します。どちらもなければ「情報なし」と表示します。
## 学び
### 1. 選択状態の管理パターン
`Set<string>` + `string[]` の組み合わせは、高速検索と順序保持を両立する良いパターンです。
正直なところ、実装当初は配列だけで管理しようとしていましたが、検索性能の問題に気づきました。個人的には、この組み合わせパターンを知っておけば、他の選択機能でも応用できると感じています。
### 2. Prune Logicの重要性
外部状態(お気に入りアイテム)が変化したら、依存する状態(選択)を自動同期します。`useEffect` で監視することで整合性を保証します。
実際に、この同期処理を忘れていて「お気に入りアイテムを削除しても比較テーブルに残り続ける」というバグに遭遇しました。`useEffect` の依存配列を意識することの重要性を痛感しました。
### 3. メタデータ駆動設計
比較項目を `COMPARE_FIELDS` 配列で定義することで、項目の追加・削除が容易です。各フィールドに `getValue` と `getNormalizedValue` を持たせることで、表示と比較のロジックを分離しています。
### 4. モーダルのアクセシビリティ
フォーカストラップとスクロールロックは別々の責務です。カスタムフック化することで再利用性が向上します(後のリファクタリングで `useFocusTrap`、`useScrollLock` に分離)。
## テスト戦略
- **比較モードの切り替え**: トグルON/OFFで選択状態がクリアされるか
- **選択操作**: 2〜4個のアイテム選択、最大数到達時の無効化
- **比較テーブル表示**: 2個以上選択時にボタンが有効化
- **Prune Logic**: お気に入り削除時に選択から自動除外
- **差異ハイライト**: 値が異なる行が黄色背景になるか
全54テスト実装、すべて通過しました。
## よくある質問:React複数選択機能の実装について
### Q1: Reactで複数選択機能を実装する最も簡単な方法は?
**A**: useStateと配列を使うのが最も簡単です。以下のコードで基本的な複数選択が実装できます。
```typescript
const [selectedIds, setSelectedIds] = useState<string[]>([]);
const toggleSelection = (id: string) => {
setSelectedIds(prev =>
prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]
);
};
```
ただし、選択数が多くなる場合は、本記事で紹介しているSetと配列の組み合わせパターンが推奨されます。
### Q2: useStateで選択状態を管理する際のパフォーマンスは?
**A**: 小規模(100件以下)であれば配列のみで問題ありません。中規模以上ではSetとの併用で検索パフォーマンスが向上します。
- 配列のみ: O(n)の検索コスト
- Setのみ: O(1)の検索コスト(順序保持なし)
- Set + 配列: O(1)の検索 + 順序保持
### Q3: モーダルのフォーカストラップとは何ですか?
**A**: フォーカストラップとは、キーボードユーザーがTabキーで操作する際、フォーカスがモーダル外に逃げないようにするアクセシビリティ機能です。
具体的には以下を実装します。
- 最初の要素でShift+Tab時に最後の要素にフォーカス
- 最後の要素でTab時に最初の要素にフォーカス
- モーダルが開いた時に最初のフォーカス可能要素にフォーカス
- モーダルが閉じた時に元の要素にフォーカスを戻す
### Q4: Prune Logicとはどういう意味ですか?
**A**: Prune(剪定)Logicとは、外部状態が変化した際に、依存する状態から不要な要素を自動的に削除するパターンです。
本記事の例では、お気に入りアイテムが削除されたら、選択状態から自動的に除外する処理を指します。
### Q5: Reactモーダル実装でよくあるバグは?
**A**: よくあるバグと対策は以下の通りです。
| バグ | 原因 | 対策 |
|-----|------|------|
| 背景スクロールが有効 | bodyのoverflow設定忘れ | `overflow: hidden`を適用 |
| フォーカスが逃げる | フォーカストラップ未実装 | Tabキーでループ処理を実装 |
| ESCキーで閉じない | イベントリスナー未設定 | keydownイベントを監視 |
| 重複レンダリング | 不適切な依存配列 | useEffectの依存配列を最適化 |
## まとめ:React複数選択比較機能の実装ガイド
本記事では、Reactで複数選択比較機能を実装する方法について解説しました。
### 重要なポイント
1. **選択状態管理**: useStateでSetと配列を組み合わせると、高速検索と順序保持を両立できます
2. **Prune Logic**: 外部状態が変化したら、useEffectで自動的に同期します
3. **アクセシビリティ**: フォーカストラップとスクロールロックは別々の責務として実装します
4. **メタデータ駆動**: 比較項目を配列で定義すると、拡張性が高まります
### 次のステップ
この実装パターンは、比較機能以外にも以下のようなケースで応用できます。
- ショッピングサイトの商品比較
- 不動産サイトの物件比較
- サービス比較サイトの機能比較
- プラン比較・料金表の実装
記事内で紹介したコードは、すべて実際に動作する実装です。
ぜひ参考にして、自分のプロジェクトで複数選択機能を実装してみてください。

はじめに:Reactで複数選択比較機能を実装する方法
お気に入り一覧ページに「複数のアイテムを横並びで比較する機能」が必要になりました。
ユーザーが2〜4個のアイテムを選択し、価格・サービス・営業時間などの情報を一覧で比較できるモーダル形式のUIを実装しました。
本記事では、Reactで複数選択機能を実装する方法について、実際のコード例を交えながら詳しく解説します。
具体的には以下のトピックをカバーします。
- useStateを使った選択状態管理のベストプラクティス
- Setと配列を組み合わせた高速な選択パターン
- Prune Logicによる外部状態との同期方法
- モーダルのアクセシビリティ対応(フォーカストラップ、スクロールロック)
- 実践的なテスト戦略
こんな人におすすめ
- Reactで複数選択機能を実装したい方
- useStateを使った選択状態管理のベストプラクティスを知りたい方
- Reactモーダルのアクセシビリティ対応(フォーカストラップ)に関心がある方
- Prune Logic(外部状態との同期)を実装したい方
- 比較機能やテーブル表示を実装する際の設計パターンを学びたい方
目次
React比較機能の要件定義
実装する比較機能の要件を整理します。
- 比較モードのON/OFF切り替えができること
- 2〜4個のアイテムを選択可能(選択順で表示)
- モーダル形式で横並び比較テーブルを表示
- アイテム間で値が異なる行を黄色背景でハイライト
- お気に入り解除時に選択状態を自動同期(prune logic)
- フォーカストラップ+スクロールロック対応
- ESCキー、オーバーレイクリック、閉じるボタンで閉じます
stateDiagram-v2
[*] --> 通常モード
通常モード --> 比較モード: トグルON
比較モード --> 通常モード: トグルOFF
比較モード --> 比較テーブル表示: 2社以上選択
比較テーブル表示 --> 比較モード: 選択数が2社未満
比較テーブル表示 --> 通常モード: 閉じる操作
note right of 比較モード
最大4社まで選択可能
選択順を保持
end note
Reactでの実装方針:useStateと型定義
1. 型定義と定数(src/types/compare.ts)
export const MAX_COMPARE_SELECTION = 4;
export const MIN_COMPARE_SELECTION = 2;
export interface CompareField {
key: string;
label: string;
icon?: string;
getValue: (company: Company) => string | string[];
getNormalizedValue: (company: Company) => string;
}
export const COMPARE_FIELDS: CompareField[] = [
{ key: 'unitPrice', label: '単価', /* ... */ },
{ key: 'wasteTypes', label: '対応廃棄物', /* ... */ },
// ...
];
比較項目をメタデータ駆動で定義。拡張性を確保。
2. useStateで複数選択状態を管理する方法
const [isCompareMode, setIsCompareMode] = React.useState(false);
const [selectedForCompare, setSelectedForCompare] = React.useState<Set<string>>(new Set());
const [selectedOrder, setSelectedOrder] = React.useState<string[]>([]);
const [showCompareTable, setShowCompareTable] = React.useState(false);
Set で選択状態を管理します(O(1)の存在チェック)
- 配列で選択順を保持します(表示順を制御)
graph LR
A[Set<string>] -->|高速検索 O1| B[選択状態管理]
C[string配列] -->|順序保持| D[表示順制御]
B --> E[選択操作]
D --> E
style A fill:#e1f5fe
style C fill:#fff3e0
style E fill:#c8e6c9
3. Prune Logic:外部状態と選択状態の同期方法
React.useEffect(() => {
setSelectedForCompare(prev => {
const pruned = new Set([...prev].filter(id => bookmarkedIds.has(id)));
if (pruned.size < MIN_COMPARE_SELECTION && showCompareTable) {
setShowCompareTable(false);
}
return pruned;
});
setSelectedOrder(prev => prev.filter(id => bookmarkedIds.has(id)));
}, [bookmarkedIds, showCompareTable]);
お気に入りアイテムが削除されたら、選択状態から自動的に除外します。最小選択数を下回ったら比較テーブルを閉じます。
Prune Logicとは、外部状態(お気に入り)が変化した際に、依存する状態(選択)を自動的に同期するパターンです。
flowchart TD
A[お気に入り削除] --> B{選択状態に含まれる?}
B -->|はい| C[選択状態から除外]
B -->|いいえ| D[何もしない]
C --> E{選択数 < 2?}
E -->|はい| F[比較テーブルを閉じる]
E -->|いいえ| G[表示を維持]
style A fill:#ffcdd2
style F fill:#fff9c4
style G fill:#c8e6c9
4. Reactモーダルのアクセシビリティ対応
アクセシビリティ対応はモーダル実装で最も重要な要素です。
- フォーカストラップ: キーボードユーザーがTabキーで操作する際、フォーカスがモーダル外に逃げないようにする機能
- スクロールロック:
body に overflow: hidden を適用
- ESCキー対応:
keydown イベントで閉じる処理
※ フォーカストラップの詳細な実装方法は、後述の「Q3: モーダルのフォーカストラップとは何ですか?」で解説しています。
5. 比較データの差異ハイライト実装
export function hasValueDifference(
companies: Company[],
field: CompareField
): boolean {
const normalizedValues = companies.map(field.getNormalizedValue);
const uniqueValues = new Set(normalizedValues);
return uniqueValues.size > 1;
}
正規化した値で比較します。1つでも異なる値があれば true です。
ポイント
選択順の保持
const handleToggleCompareSelection = (companyId: string) => {
setSelectedForCompare(prev => {
const newSet = new Set(prev);
if (newSet.has(companyId)) {
newSet.delete(companyId);
setSelectedOrder(order => order.filter(id => id !== companyId));
} else if (newSet.size < MAX_COMPARE_SELECTION) {
newSet.add(companyId);
setSelectedOrder(order => [...order, companyId]);
}
return newSet;
});
};
Set と配列を同時に更新します。Setで高速検索、配列で順序を保証します。
イベント伝播の制御(アイテムカード)
比較モード時はカードクリックで選択切替、通常モードは詳細モーダル表示します。
const handleCardClick = () => {
if (isCompareMode) {
if (!isSelectionDisabled || isSelectedForCompare) {
onToggleCompareSelection?.();
}
} else {
onCardClick();
}
};
お気に入り解除ボタンは stopPropagation() でカードクリックに影響しないようにします。
データフォールバック
const operatingHours = company.operatingHours ||
(company.businessHours ? `平日: ${company.businessHours}` : '情報なし');
operatingHours が空なら businessHours から生成します。どちらもなければ「情報なし」と表示します。
学び
1. 選択状態の管理パターン
Set<string> + string[] の組み合わせは、高速検索と順序保持を両立する良いパターンです。
正直なところ、実装当初は配列だけで管理しようとしていましたが、検索性能の問題に気づきました。個人的には、この組み合わせパターンを知っておけば、他の選択機能でも応用できると感じています。
2. Prune Logicの重要性
外部状態(お気に入りアイテム)が変化したら、依存する状態(選択)を自動同期します。useEffect で監視することで整合性を保証します。
実際に、この同期処理を忘れていて「お気に入りアイテムを削除しても比較テーブルに残り続ける」というバグに遭遇しました。useEffect の依存配列を意識することの重要性を痛感しました。
3. メタデータ駆動設計
比較項目を COMPARE_FIELDS 配列で定義することで、項目の追加・削除が容易です。各フィールドに getValue と getNormalizedValue を持たせることで、表示と比較のロジックを分離しています。
4. モーダルのアクセシビリティ
フォーカストラップとスクロールロックは別々の責務です。カスタムフック化することで再利用性が向上します(後のリファクタリングで useFocusTrap、useScrollLock に分離)。
テスト戦略
- 比較モードの切り替え: トグルON/OFFで選択状態がクリアされるか
- 選択操作: 2〜4個のアイテム選択、最大数到達時の無効化
- 比較テーブル表示: 2個以上選択時にボタンが有効化
- Prune Logic: お気に入り削除時に選択から自動除外
- 差異ハイライト: 値が異なる行が黄色背景になるか
全54テスト実装、すべて通過しました。
よくある質問:React複数選択機能の実装について
Q1: Reactで複数選択機能を実装する最も簡単な方法は?
A: useStateと配列を使うのが最も簡単です。以下のコードで基本的な複数選択が実装できます。
const [selectedIds, setSelectedIds] = useState<string[]>([]);
const toggleSelection = (id: string) => {
setSelectedIds(prev =>
prev.includes(id) ? prev.filter(x => x !== id) : [...prev, id]
);
};
ただし、選択数が多くなる場合は、本記事で紹介しているSetと配列の組み合わせパターンが推奨されます。
Q2: useStateで選択状態を管理する際のパフォーマンスは?
A: 小規模(100件以下)であれば配列のみで問題ありません。中規模以上ではSetとの併用で検索パフォーマンスが向上します。
- 配列のみ: O(n)の検索コスト
- Setのみ: O(1)の検索コスト(順序保持なし)
- Set + 配列: O(1)の検索 + 順序保持
Q3: モーダルのフォーカストラップとは何ですか?
A: フォーカストラップとは、キーボードユーザーがTabキーで操作する際、フォーカスがモーダル外に逃げないようにするアクセシビリティ機能です。
具体的には以下を実装します。
- 最初の要素でShift+Tab時に最後の要素にフォーカス
- 最後の要素でTab時に最初の要素にフォーカス
- モーダルが開いた時に最初のフォーカス可能要素にフォーカス
- モーダルが閉じた時に元の要素にフォーカスを戻す
Q4: Prune Logicとはどういう意味ですか?
A: Prune(剪定)Logicとは、外部状態が変化した際に、依存する状態から不要な要素を自動的に削除するパターンです。
本記事の例では、お気に入りアイテムが削除されたら、選択状態から自動的に除外する処理を指します。
Q5: Reactモーダル実装でよくあるバグは?
A: よくあるバグと対策は以下の通りです。
| バグ |
原因 |
対策 |
| 背景スクロールが有効 |
bodyのoverflow設定忘れ |
overflow: hiddenを適用 |
| フォーカスが逃げる |
フォーカストラップ未実装 |
Tabキーでループ処理を実装 |
| ESCキーで閉じない |
イベントリスナー未設定 |
keydownイベントを監視 |
| 重複レンダリング |
不適切な依存配列 |
useEffectの依存配列を最適化 |
まとめ:React複数選択比較機能の実装ガイド
本記事では、Reactで複数選択比較機能を実装する方法について解説しました。
重要なポイント
- 選択状態管理: useStateでSetと配列を組み合わせると、高速検索と順序保持を両立できます
- Prune Logic: 外部状態が変化したら、useEffectで自動的に同期します
- アクセシビリティ: フォーカストラップとスクロールロックは別々の責務として実装します
- メタデータ駆動: 比較項目を配列で定義すると、拡張性が高まります
次のステップ
この実装パターンは、比較機能以外にも以下のようなケースで応用できます。
- ショッピングサイトの商品比較
- 不動産サイトの物件比較
- サービス比較サイトの機能比較
- プラン比較・料金表の実装
記事内で紹介したコードは、すべて実際に動作する実装です。
ぜひ参考にして、自分のプロジェクトで複数選択機能を実装してみてください。