React特訓03: ドロップダウンメニューでカテゴリーを選択→それに合わせたリストを表示させる

# はじめに
私がReactを学習するにあたって、AIに頼らずコードを描けるようになるために解いた問題を、アウトプットとして残していきます。

この問題はAIを使用して作成したもので、以下の流れで学習を進めたものになります。

1\. AIに問題を作らせる
2\. 調べながらやってみる
3\. 困ったらAIに質問する
4\. AIにレビューしてもらう

## 問題
ユーザーがドロップダウンメニューからカテゴリーを選択すると、それに合わせて関連する項目リストが表示されるコンポーネントを作ろう

### 要件
- ドロップダウンメニューでカテゴリー(例：食べ物、飲み物、デザート)を選べるようにする
- カテゴリを選択すると、そのカテゴリに関連づけられた項目(例：食べ物→「ポテチ,ポッキー,うまい棒」)がリストで表示される
- 初期値はリストは表示されていない

### ポイント
- useStateを使った選択項目の状態管理
- 配列やオブジェクトのデータを条件付きで画面に表示する
- Reactのselect要素を使ったカテゴリ分けと動的な表示制御

### 完成系
- 初期状態 
![スクリーンショット 2025-05-05 9.15.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842446/b0cd3782-a24b-4bde-a5b0-0cea2621b73b.png)
- ドロップダウン展開
![スクリーンショット 2025-05-05 9.16.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842446/a3672b37-698c-493b-8874-7a4631c84c3f.png)
- それぞれをクリック
![スクリーンショット 2025-05-05 9.16.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842446/489eed37-e225-405d-8d60-ba845ccd80dc.png)
![スクリーンショット 2025-05-05 9.16.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842446/0094c28a-ce0d-4235-8c92-113e9096ba4c.png)
![スクリーンショット 2025-05-05 9.17.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842446/cb618eb3-7fe0-475c-ad2d-827105c3dd20.png)

## 解答
```jsx
import React, { useState } from 'react';

function DynamicList() {

  const [selectedCategory, setSelectedCategory] = useState(``);
  const categoryItems = {
    food: ['ポテチ', 'ポッキー', 'うまい棒'],
    drink: ['コーラ', 'ファンタ', 'スプライト'],
    desert: ['ゼリー', 'プリン', 'アイス'],
  }
  
  const handleCategoryChange = (e) => {
    setSelectedCategory(e.target.value)
  }

  return (
    <div className="p-8">
      <select className="h-14 w-[300px] bg-white appearance-none border border-blue-500 rounded-lg p-3" onChange={handleCategoryChange} value={selectedCategory}>
        <option value="">カテゴリーを選択してください</option>
        <option value="food">食べ物</option>
        <option value="drink">飲み物</option>
        <option value="desert">デザート</option>
      </select>
      <div className="mt-4">
        <ul>
          {selectedCategory &&
            categoryItems[selectedCategory].map((item, index) => <li key={index} className="w-[300px] border border-blue-200 rounded-md px-4 py-2 mb-2">{item}</li>)}
        </ul>
      </div>
    </div>
  )
}

export default DynamicList;
```

### 解説
記述の手順
1\. 関数コンポーネントを作成
2\. 選択されたカテゴリを管理する`state`を作成
3\. カテゴリごとの項目を作成
4\. UIを作成
5\. カテゴリを選択したときに、選択したカテゴリ名が表示されるようにする
6\. イベントを作成し更新関数に値を渡す
7\. `map`メソッドでリストを表示

以下から順に進めます。

--- 
#### 1\.  関数コンポーネントを作成
```jsx
function DynamicList() {
```
---
#### 2\. 選択されたカテゴリを管理する`state`を作成
```jsx
const [selectedCategory, setSelectedCategory] = useState(``);
```
---
#### 3\. カテゴリごとの項目を作成
```jsx
  const categoryItems = {
    food: ['ポテチ', 'ポッキー', 'うまい棒'],
    drink: ['コーラ', 'ファンタ', 'スプライト'],
    desert: ['ゼリー', 'プリン', 'アイス'],
  }
```
---
#### 4\. UIを作成
TailWindを使用してお好みのスタイルに調整
```jsx
<div className="p-8">
      <select className="h-14 w-[300px] bg-white appearance-none border border-blue-500 rounded-lg p-3">
        <option value="">カテゴリーを選択してください</option>
        <option value="food">食べ物</option>
        <option value="drink">飲み物</option>
        <option value="desert">デザート</option>
      </select>
      <div className="mt-4">
        <ul>
            <li className="w-[300px] border border-blue-200 rounded-md px-4 py-2 mb-2">
                {項目を表示}
            </li>
        </ul>
      </div>
</div>
```
---
#### 5\. カテゴリを選択したときに、選択したカテゴリ名が表示されるようにする
`value`属性を使用して`state`と同期させる。
まだイベントは作成していないので、またクリックしても反映されない。
```jsx
<select className="h-14 w-[300px] bg-white appearance-none border border-blue-500 rounded-lg p-3" value={selectedCategory}>
```
---
#### 6\. イベントを作成し更新関数に値を渡す
今回はユーザーが変更を加えたときにイベントが発火して欲しいので、`onClick`ではなく`onChange`を使用する。
ユーザーがカテゴリを変更すると`handleCategoryChange`関数が発火し、更新関数にイベントによって選ばれた値を取得し、`state`に保存する。
```jsx
const handleCategoryChange = (e) => {
    setSelectedCategory(e.target.value)
  }

return (
    <div className="p-8">
      <select className="h-14 w-[300px] bg-white appearance-none border border-blue-500 rounded-lg p-3" onChange={handleCategoryChange} value={selectedCategory}>
```
---
#### 7\. `map`メソッドでリストを表示
`categoryItems`の選択されているカテゴリ(現在の`state`)の配列を展開。
各`item`に`index`というキーを持たせReactが識別できるようにする。
実務においては、キーに`index`を使用するのはアンチパターンなので注意。
```jsx
<ul>
    {selectedCategory &&
        categoryItems[selectedCategory].map((item, index) => <li key={index} className="省略">{item}</li>)}
 </ul>
```