【React】Material UIを使った一番シンプルなサイドバー実装

# はじめに
本記事では下記のようなシンプルなサイドバーを作成することを目的とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3770170/008ebb98-e2c9-9bba-71aa-962db8f440b5.png)

なお、レスポンシブルデザインにも対応するためにMaterial UIを活用します。
「サイドバー　作り方」の検索で出てくる記事・動画だと意外と実践的な内容が少ないため、参考になるかと思います。

# 作り方の全体像
### フォルダ構成
Sidebar.jsとSidebarData.jsの二つのファイルを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3770170/c8cf9312-3fd3-7543-ffa4-f1383451731b.png)

Sidebar.jsではレスポンシブルなサイドバーの見た目を実装し、SidebarData.jsでは表示する項目（ホームやログイン）を表形式で管理します。

### 使い方
コンポーネントとして、いつでもSidebarが呼び出せる状態にして使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3770170/f660b9a1-d14f-dcc0-7d89-3f6d3491a027.png)

# 実装
## 事前準備
必要なライブラリをインストールします。エラーが出る場合はライブラリが足りない可能性があるため、ChatGPTにエラーを食わせて、足りないライブラリを教えてもらいご自身でnpm installして下さい。
```
npm install @mui/material @emotion/react @emotion/styled
```

## Sidebar.js

### スタイリング
- StyledDrawer: Drawerコンポーネントをカスタマイズして幅と背景色を設定
- StyledListItem: ListItemコンポーネントをカスタマイズして色とホバー時の背景色を設定
```js
const StyledDrawer = styled(Drawer)(({ theme }) => ({
  width: 250,
  flexShrink: 0,
  '& .MuiDrawer-paper': {
    width: 250,
    boxSizing: 'border-box',
    background: '#2d445d',
  },
}));

const StyledListItem = styled(ListItem)(({ theme }) => ({
  color: 'white',
  '&:hover': {
    backgroundColor: '#3b627a',
  },
}));

```

### SidebarIconコンポーネント
- サイドバー上部に表示されるアイコンとテキストのリンクコンポーネント。
```js
const SidebarIcon = () => (
  <Link to="/" style={{ textDecoration: 'none', color: 'inherit' }}>
    <Box display="flex" flexDirection="column" alignItems="center" py={2}>
      <img src={Icon} alt="Icon" style={{ width: 100 }} />
      <Typography variant="subtitle1" fontWeight={600} color="white">
        FootBallApp
      </Typography>
    </Box>
  </Link>
);

```

### Sidebarコンポーネント
- theme, isMobile: Material-UIのテーマとメディアクエリを使用してレスポンシブデザインを実現
- mobileOpen: モバイルでのドロワーの開閉状態を管理するためのステート
- handleDrawerToggle: ドロワーの開閉をトグルする関数
- drawer: ドロワーの内容を定義。Toolbar、SidebarIcon、リンクのリストを含む
- IconButton: モバイルビューでのメニューボタン
- StyledDrawer: モバイルビューでは一時的なドロワー、デスクトップビューでは常に表示されるドロワー

このサイドバーは、レスポンシブデザインであり、モバイルとデスクトップの両方に対応しています。モバイルでは、メニューボタンをクリックするとドロワーが開閉します。デスクトップでは常に表示されます。

```js
function Sidebar() {
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
  const [mobileOpen, setMobileOpen] = React.useState(false);

  const handleDrawerToggle = () => {
    setMobileOpen(!mobileOpen);
  };

  const drawer = (
    <>
      <Toolbar />
      <SidebarIcon />
      <List>
        {SidebarData.map((item, index) => (
          <StyledListItem button component={Link} to={item.link} key={index}>
            <ListItemIcon sx={{ color: 'white' }}>{item.icon}</ListItemIcon>
            <ListItemText primary={item.title} />
          </StyledListItem>
        ))}
      </List>
    </>
  );

  return (
    <>
      <IconButton
        color="inherit"
        aria-label="open drawer"
        edge="start"
        onClick={handleDrawerToggle}
        sx={{ mr: 2, display: { sm: 'none' } }}
      >
        <MenuIcon />
      </IconButton>
      <StyledDrawer
        variant={isMobile ? 'temporary' : 'permanent'}
        open={isMobile ? mobileOpen : true}
        onClose={handleDrawerToggle}
        ModalProps={{ keepMounted: true }}
      >
        {drawer}
      </StyledDrawer>
    </>
  );
}

```
## SidebarData.js
表示項目は以下のようにディクショナリ型で管理します。
```SidebarData.js
import React from 'react';
import HomeIcon from '@mui/icons-material/Home';
import LoginIcon from '@mui/icons-material/Login';

const SidebarData = [
  { title: "ホーム", icon: <HomeIcon />, link: "/" },
  { title: "ログイン", icon: <LoginIcon />, link: "/login" }
];

export default SidebarData;
```
表示しているアイコンについてはMUIに準備されているアイコンを活用します。下記のようにサイトからコードをコピーすればそのまま活用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3770170/5e889d24-857d-98ad-3a57-26b911a053b4.png)



# Material UIについての補足
Drawerは、Material-UIライブラリで提供されているコンポーネントの一つで、サイドバーやナビゲーションメニューを実装するために使用されます。Drawerは画面の端からスライドインするパネルで、通常はナビゲーションリンクや他の重要なコンテンツを含むために使われます。

#### Drawerの特徴
1. スライドインパネル:
画面の左側、右側、上部、または下部からスライドインすることができます。
2. 常時表示または一時表示:
永続的に表示する「permanent」モードや、必要に応じて表示する「temporary」モードがあります。
3. レスポンシブ対応:
画面サイズに応じて動作を変更でき、モバイルデバイスでは一時的なドロワーを使用し、デスクトップでは永続的なドロワーを使用することが一般的です。

# まとめ
Sidebarをコンポーネントにして扱えるのはReactの強みだと思います。
再現性・汎用性を持たせるためにもMaterial UIはフル活用するのが良いと思います。