Reactの勉強④　メニューとサイト

**今回の狙い**
Web画面の機能といえば、メニューがあり、色々なサブ画面から成り立つ　と。
今回は、今までの環境をそのまま流用して、その辺りを作ってみたいと思います。

**実装**
多く見えますが、site1～site3までは、今までの勉強①～③の寄せ集めです。
今回は、「Menu.js」だけとなってます。
```diff_conf:フォルダ構成
└── src
　　 ├── site1　　　　　 　（勉強１のRestAPIと一覧表示）
　　 |    └── WebApi.js　　　 （index.jsは不要）
　　 ├── site2　　　　　 　（勉強２の入力画面）
　　 |    ├── App.js 　　　　 （index.jsは不要）
　　 |    ├── ErrCheck.js 　　（入力チェック処理部）
　　 |    └── msg.jp.js　　　 （エラーメッセージ）
　　 ├── site3　　　　 　　（勉強３のポップアップ）
　　 |    ├── components  　　（画面プログラム）
　　 |    |　　├── Form.js　　　 　（入力画面処理）
　　 |    |　　└── AlertDialog.js　（ポップアップ画面処理）
　　 |    └── pages 　　　　　 （index.jsは不要）
　　 |     　　└── App.js　　　　　（画面制御処理）
　　 ├── Menu.js　 （★今回の主役★） 
　　 └── index.js　（カレントパスの起動プログラム）
```
以下、起動プログラムはいつも通りです。
```diff_javascript:index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './Menu';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
```
以下が本丸のプログラムです。
```diff_javascript:Menu.js
import { useState } from 'react';
import App1 from './site1/WebApi';
import App2 from './site2/App';
import App3 from './site3/pages/App';
import { Box, IconButton, Drawer, List, ListItem, ListItemButton, ListItemText, ListItemIcon } from '@mui/material';
import { Home, Add, Message, Menu } from '@mui/icons-material';
import ListIcon from '@mui/icons-material/List';
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
const menu = [
  { title: 'ホーム', href: '/', icon: Home },
  { title: 'Redmineユーザ一覧', href: '/list', icon: ListIcon },
  { title: 'Redmineユーザ登録', href: '/add', icon: Add },
  { title: 'ポップアップ', href: '/dialog', icon: Message },
];

export default function Menu1() {
  const [show, setShow] = useState(false);
  const handleDraw = () => setShow(!show);
  return (
    <>
    <Box mb={2}>
      <IconButton onClick={handleDraw} color="inherit" aria-label="menu">
        <Menu />
      </IconButton>
    </Box>
    <BrowserRouter>
      <Routes>
          <Route path="/" element={<p>お知らせ・・・</p>} />
          <Route path="/list" element={<App1 />} />
          <Route path="/add" element={<App2 />} />
          <Route path="/dialog" element={<App3 />} />
      </Routes>
      <Drawer anchor="left" open={show}>
        <Box sx={{ height: '100vh' }} onClick={handleDraw}>
          <List>
          {menu.map(obj => {
            const Icon = obj.icon;
            return (
              <ListItem key={obj.title}>
                <ListItemButton component={Link} to={obj.href}>
                  <ListItemIcon><Icon /></ListItemIcon>
                  <ListItemText primary={obj.title} />
                </ListItemButton>
              </ListItem>
            );
          })}
          </List>
        </Box>
      </Drawer>
    </BrowserRouter>
    </>
  );
}
```
実行すると、以下のようなメニューが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3878922/4d2eee44-b670-46e9-80d3-a647c69644c9.png)

アイコン画像は、色々と準備されているのですが、下記のURLから検索が可能です。
https://mui.com/material-ui/material-icons/

ここまで色々とまとめられると、「もっとイケル」と思う訳で。。。
簡単に出来そう…　と思うと、罠が待ち受けます。
例えば、今回用意したプログラム群を１階層下のフォルダにまとめたいと…。
（例として、「sub」のフォルダ配下に、全てを配置します）
そんな時のコツとして、呼び出し元で下層の複数のリンクに対応する為、パスに*が付きます。
（下層のMenuは、区別する為、「Menu1.js」に変更）
```diff_javascript:上層.js（Menu.js）
import App from './sub/Menu1';　（下層のLinkプログラム）
・・・
const menu = [
  { title: 'ホーム', href: '/', icon: Home },
  { title: 'サブ', href: '/sub', icon: Message },
・・・
      <Routes>
          <Route path="/" element={<p>お知らせ・・・</p>} />
          <Route path="/sub/*" element={<App />} />　（下層は/sub/・・・となります）
      </Routes>
```
下層のLinkプログラムも改修が必要です。
```diff_javascript:下層.js（Menu1.js）
・・・
const menu = [
  { title: 'ホーム', href: '', icon: Home },
  { title: 'Redmineユーザ一覧', href: 'list', icon: ListIcon },　（パスの頭の/は削除）
・・・　（<BrowserRouter>のタグは削除する必要があります）
      <Routes>
          <Route path="dialog" element={<App3 />} />　（パスの頭の/は削除）
・・・
```
コツが解れば、画面単位に開発者が別で、大規模開発も狙えそうですね。
以上、御疲れ様でした～。