Material-UIで一覧画面を作ってみる（React）

# はじめに
今回は、Material-UIの使い方や使ってみた所感を書いていきたいと思います。

# Material-UIとは
Material-UIとは、Googleのマテリアルデザインの仕様を取り入れているReact用のUIコンポーネントライブラリです。Material-UIを利用することで手軽に見栄えの良いコンポーネントを作成することができます。

▶ [Material-UI](https://material-ui.com/ja/ "Material-UI")


### マテリアルデザインとは
マテリアルデザインとは、Googleが提唱している物質的なデザインのガイドラインです。スマートフォンやタブレットなどのタッチデバイスの普及により直感的に操作ができるUIへの需要が高まってきた中で生まれた概念です。

▶ [Material Design](https://material.io/ "Material Design")

# 環境
今回の使用バージョンはそれぞれ以下の通りです。

* Node.js v12.19.0
* React v16.13.1
* @material-ui/core v4.11.0

# Material-UIの導入
次のコマンドを実行し、Material-UIをインストールします。

```bash
# npmの場合
npm install @material-ui/core

# yarnの場合
yarn add @material-ui/core
```

# ディレクトリ構成
ディレクトリ構成は以下のようになります。今回はあくまでも簡単なページを作成することを目的としているため、Reactを使用しシステムを作成する場合は、様々な構成を調査し作成したいシステムに合った構成を探してみてください！

▶ [Reactのファイル構成について](https://ja.reactjs.org/docs/faq-structure.html "Reactのファイル構成について")


```
src/
 ├ components/
 │　└ header.js   
 │　└ card.js     
 ├ pages/
 │　└ _app.js     
 │　└ _document.js     
 │　└ index.js     
 ├ public/
 │　└ image/
 │  　└ ika.png
 └ package.json
```

# 早速使ってみる
今回は公式ドキュメントのソースコードを参考に一覧画面を作成しながら、Material-UIによって作成できるコンポーネントを紹介していきます。

### ページの骨組みを用意する
これから作成するコンポーネント達を配置するために、ページの骨組みを用意します。

```jsx:pages/index.js
import { Header } from '../components/header';
import { Card } from '../components/card';

const Index = () => (
  <div>
    <Header />
    <Card />
  </div>
)

export default Index
```

表示させてもまだ何もないので真っ白のページが表示されますが、確認方法を説明します。
以下のコマンドでローカルホストを立ち上げ、`http://localhost:3000/`にアクセスすることで確認できます。

```bash
# npmの場合
npm run dev

# yarnの場合
yarn dev
```

※`components/header.js`などインポート宣言しているファイルを作成していないとエラーになるのでご注意ください。

### ヘッダーを作成してみる
まずはWebサイトには欠かせないヘッダーを作成していきます。早速書いてみましょう！
実際のコードは以下になります。

```jsx:components/header.js
export const Header = () => {
  const classes = useStyles();

  return (
    <div className={classes.root}>
      <AppBar position="static">
        <Toolbar>
          <IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" className={classes.title}>
            TOP
          </Typography>
        </Toolbar>
      </AppBar> 
    </div>
  );
}

```
`Appbar`や`Typography`などのタグはインポートをすることで使用できます。
`className={classes.root}`の記述ではタグにクラス属性を付与し、見た目を調整することができます。

結果は以下になります。シンプルなヘッダーを作成することができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185610/5217c998-7bfc-5f9f-2936-a8a204962b7a.png)


せっかくなのでメニューアイコンを動くようにしてみましょう！以下のように書いていきます。

```jsx:components/header.js
export const Header = () => {
  const classes = useStyles();
  const theme = useTheme();
  // stateとstateを更新するための関数を宣言
  const [open, setOpen] = React.useState(false);

  // メニューを開く関数
  const handleDrawerOpen = () => {
    setOpen(true);
  };

  // メニューを閉じる関数
  const handleDrawerClose = () => {
    setOpen(false);
  };

  return (
    <div className={classes.root}>
      <CssBaseline />
      <AppBar
        position="fixed"
        className={clsx(classes.appBar, {
          [classes.appBarShift]: open,
        })}
      >
        <Toolbar>
          {/* メニューアイコンクリック時に呼び出す関数を定義 */}
          <IconButton
            color="inherit"
            aria-label="open drawer"
            onClick={handleDrawerOpen}
            edge="start"
            className={clsx(classes.menuButton, open && classes.hide)}
          >
            <MenuIcon />
          </IconButton>
          <Typography variant="h6" noWrap>
            TOP
          </Typography>
        </Toolbar>
      </AppBar>
      {/* メニュー部分 */}
      <Drawer
        className={classes.drawer}
        variant="persistent"
        anchor="left"
        open={open}
        classes={{
          paper: classes.drawerPaper,
        }}
      >
        <div className={classes.drawerHeader}>
          {/* 閉じるアイコンクリック時に呼び出す関数を定義 */}
          <IconButton onClick={handleDrawerClose}>
            {theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
          </IconButton>
        </div>
        <Divider />
        <List>
          {links.map((link) => (
            <ListItemLink href={link.link} key={link.id}>
              <ListItemText primary={link.label} />
            </ListItemLink>
          ))}
        </List>
      </Drawer>
      <main
        className={clsx(classes.content, {
          [classes.contentShift]: open,
        })}
      >
      </main>
    </div>
  );
}
```

先ほどのシンプルなヘッダーに比べて記述量は増えましたが、簡単ですね。
Reactではコンポーネントの状態を管理するために`state`を使用します。stateの更新には`setState`を使用します。この例ではメニューアイコンをクリックしたときにメニューを開くために、`open`というstateで状態を管理しています。

無事動かすことができました！

![header.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185610/5442df5c-9cb8-0c4e-f65a-c51d038c49c3.gif)

### コンテンツを作成する

続いてコンテンツを作成します。今回はカードを並べるような感じでコンテンツを一覧表示させますので、カードのコンポーネントを作成していきます。

```jsx:components/card.js
export const Card = () => {
  const classes = useStyles();

  return (
    <div className={classes.main}>
      <Card className={classes.root}>
        <CardActionArea>
          <CardMedia
            className={classes.media}
            image="イメージパス"
            title="Contemplative Reptile"
          />
          <CardContent>
            <Typography gutterBottom variant="h5" component="h2">
              タイトル
          </Typography>
            <Typography variant="body2" color="textSecondary" component="p">
              説明
          </Typography>
          </CardContent>
        </CardActionArea>
        <CardActions>
          <Button size="small" color="primary">
            Share
        </Button>
          <Button size="small" color="primary">
            Learn More
        </Button>
        </CardActions>
      </Card>
    </div>
  );
}
```
以下のような一覧画面ができました。（上記のコードは1枚のカードを生成するコードです。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185610/88c01aa7-6025-b7eb-1737-a079e8a1a673.png)

### レスポンシブ対応について
ちなみに今回作成したページはレスポンシブ対応になっています。スマートフォンで表示したときは以下のような表示になります。驚きなのが、特にレスポンシブ対応のための実装はしていないことです。便利ですね:clap:
![SP.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1185610/57b69858-5eeb-9429-3b01-79d5b925d1eb.gif)


今回はMaterial-UIを使用し、このような一覧画面を作成することができました。簡単に見た目の良いページを作成でき扱いやすさを感じました！

# あとがき
Webシステムのクオリティを上げるには処理の精度を上げることと並行してデザインも重要ですよね。私自身、最近の業務でデザイナーさんの力を全力で感じています。
ただ、システム作成の際に見栄えを良くしたいと思ってもデザインに割く時間が無かったり、デザイナーさんに頼めないという場面もあるかと思います。そんな時は今回紹介したMaterial-UIなどのUIフレームワークを利用してみるのもいいかもしれません。Material-UI以外にも多種多様なUIフレームワークが用意されていますので気になった方はぜひ一度使ってみてください。

最後までお読みいただき、ありがとうございました:slight_smile::sunflower:

# 参考資料
https://material-ui.com/ja/

https://material.io/

https://ja.reactjs.org/docs/faq-structure.html