Material-UIの便利なコンポーネント


#目次
[1. はじめに](#1-はじめに)
[2. Material-UIの実装方法](#2-material-uiの実装方法)
[3. Grid編 - コンポーネントの画面配置を決めることができる](#3-grid編)
[4. Table編 - 表を扱える](#4-table編)
[5. Modal編 - クリックすると、モーダルウィンドウが開く](#5-modal編)
[6. 終わりに](#6-終わりに)


#1. はじめに
Material-UIとはGoogleが開発したReact, Typescriptで使えるUIライブラリです。それぞれのコンポーネントは、公式が設計したprops（組み込み要素）を組み合わせることで、見栄えの良いUIを作ることができます。しかし公式のライブラリの説明は、日本語対応していなかったり、そもそも説明不足でわかりにくい部分があります。最近私はMaterial-UIを使って開発をする機会が多かったので、今回はその中で私が便利だと感じたコンポーネントとpropsについてまとめて紹介していきたいと思います。

#2. Material-UIの実装方法
####1. Reactの開発環境を構築する。
ここでは省略しますが、以下の記事からmac, windowsでreactの環境構築ができます。
  [Macの場合](https://qiita.com/EZ_Denta/items/9e6a47f330b5a01806ae)
  [Windowsの場合](https://qiita.com/KKoh/items/8aa1bf0bb3673e8e2455)
####2. Material-uiのパッケージをtermialでインストールする。
  ```termial:termial
// with npm
npm install @material-ui/core
npm install @material-ui/icons

// with yarn
yarn add @material-ui/core
yarn add @material-ui/icons
  ```

####3. reactのファイルで自分の使いたいコンポーネントをimportして使う

```react:App.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import Button from '@material-ui/core/Button';

function App() {
  return (
    <Button variant="contained" color="primary">
      Hello World
    </Button>
  );
}

ReactDOM.render(<App />, document.querySelector('#app'));
```

#3. Grid編
Gridはコンポーネントの画面配置を決めることができます。例えば、２つの要素を画面の中央に揃えたり、右端に寄せたり、等間隔で揃えることなど、、、propsを組み合わせるだけで簡単に画面配置できるため非常に強力なコンポーネントです。
以下はGrid内で使えるpropsについてまとまめました。
####1. container, item
containerとitemは親子関係で親がcontainerとなるように使います。
container内の要素は一列で揃えることが可能で、これがGridの基本となるためGridコンポーネントを使う場合は必須のpropsです。

```react:使用例
<Grid container>//container内の要素は一列で表示
  <Grid item>
  {/* 中身 */}
  </Grid>
  <Grid item>
  {/* 中身 */}
  </Grid>
</Grid>
```

####2. justify
justifyは、containerが含まれている　Gridタグ内につけます。それぞれのitemの配置を多岐にわたって調整することが可能です。下に種類 - 用途の一覧を示しています。

+ 'flex-start' - 全てのアイテムを左端に揃える
+ 'center' - 全てのアイテムを中心に揃える
+ 'flex-end' - 全てのアイテムを右端に揃える。
+ 'space-between' - itemを等間隔に配置する。
+ 'space-around'  - itemを等間隔に配置する。space-betweenと違い、両端に空白が入る。
+ 'space-evenly' - itemを等間隔に配置する。space-aroundより、両端の空白の割合が大きい。

```react:使用例
<Grid container justify="flex-end">
  <Grid item>
  {/* 中身 */}
  </Grid>
  <Grid item>
  {/* 中身 */}
  </Grid>
</Grid>
//この場合、二つのアイテムは左揃えになる。
```

####3. spacing
containerが含まれているGridタグ内につけることで、itemの間隔を調整できます。広さは{1}~{12}で決めることができるので、画面を見ながら試してみてちょうどいい間隔となるように数を調整します。

```react:使用例
<Grid container spacing={4}>
  <Grid item>
  {/* 中身 */}
  </Grid>
  <Grid item>
  {/* 中身 */}
  </Grid>
</Grid>
//この場合、二つのアイテムの間隔が4の幅になります。
```

##Grid応用編
今までのpropsを組み合わせることで、以下のような構成にすることも可能です。

```react:コード
<Grid container justify="space-between">
  <Grid item>
    <Grid container spacing={2}>
      <Grid item>
        <Button
        variant="contained"
        color="secondary"
        startIcon={<SaveIcon />}
        >保存する
        </Button>
      </Grid>
      <Grid item>
        <Button
        variant="contained"
        color="secondary"
        startIcon={<DeleteIcon />}
        >削除する
        </Button>
      </Grid>
    </Grid>
  </Grid>
  <Grid item>
    <Button
    variant="contained"
    color="secondary"
    startIcon={<SettingsIcon />}
    >設定する
    </Button>
  </Grid>
</Grid>
```

####結果
三つのボタンの配置を一列でいい感じに整えることができています。

![スクリーンショット 2020-12-12 16.47.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849084/a298cbdb-c79d-c7f2-80aa-1f1f1adf3249.png)



#4. Table編
Tableコンポーネントは、表を作ることができます。見た目だけでなく、表の並びを変えたりページ切り替えを可能にしたりするライブラリもあり、非常に便利です。Tableの基本構成は下図のようになっています。手書きで汚くてすみません。htmlの知識があればすぐに使えると思います。
![スクリーンショット 2020-12-12 18.05.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849084/b485b4da-0e42-adb6-36db-5bb9244cf29b.png)
サンプルコードと補足の説明を入れています。

```react:サンプルコード
<TableContainer component={Paper} style={{ marginBottom: 30 }}>
{/* componentにライブラリのPaperをつけることで立体感がでてよくなります */}
  <Table>
    <TableHead>
      <TableRow style={{ backgroundColor: "#F2F2F2" }}>
        <TableCell>ID</TableCell>
        <TableCell >氏名</TableCell>
        <TableCell >ステート</TableCell>
      </TableRow>
    </TableHead>
    <TableBody>
    {rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row) => (
              //ページ切り替えの要素を取得
      <TableRow hover key={row.id}> 
       {/* hoverを入れることでマウスポイントが表の上に乗った時に色が変わるアクションがつきます */}
        <TableCell component="th" scope="row">{row.id}</TableCell>
        <TableCell >{row.name}</TableCell>
        <TableCell >{row.state}</TableCell>
      </TableRow>
      ))}
    </TableBody>
    <TableFooter>
      <TableRow>
        <TablePagination
        labelRowsPerPage="表示件数:"
        rowsPerPageOptions={[
          { label: '10件', value: 10 },
          { label: '50件', value: 50 },
          { label: '100件', value: 100 },
          { label: '全て', value: rows.length }
          ]}
         count={rows.length}
         rowsPerPage={rowsPerPage}
         page={page}
         SelectProps={{
           native: true
           }}
         onChangePage={handleChangePage}
         onChangeRowsPerPage={handleChangeRowsPerPage}
         ActionsComponent={TablePaginationActions}
         />
      </TableRow>
    </TableFooter>
  </Table>
</TableContainer>
```
####結果
![スクリーンショット 2020-12-12 18.17.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849084/ea15c721-3fb0-b1ef-556b-e7b89900eb35.png)

#5. Modal編
Modalは、ボタンやテキストなどの指定したコンポーネントをクリックするなどの条件を満たした時に表示することができます。用途としては、inputコンポーネントを埋め込んでデータを入力できるようにしたり、注意を表示させたい時に使います。
今回は、下のような新規作成ボタンを押すと、
![スクリーンショット 2020-12-12 21.05.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849084/cfa4f344-514e-99e8-2ba3-a3f62d0ac491.png)
タイトルやコメントを入力できる画面が表示されようなものを作成する手順について順を追って説明します。
![スクリーンショット 2020-12-12 20.46.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849084/cd6b9cef-399b-39fe-f851-f097f45a983e.png)

####1.ボタン（Modalが開くきっかけ）と、クリックするとtrueになる関数を作成
```react:react
import React, {useState} from 'react';
import AddCircleIcon from '@material-ui/icons/AddCircle';

function NoticeScreen()  {
  const [open, setOpen] = useState(false);
  return(
    <Button
      variant="contained"
      color="secondary"
      startIcon={<AddCircleIcon />}
      onClick={() => setOpen(true)}
      //クリックするとtrueになる
      style={{ marginTop: 30 }}
    >
      新規作成
    </Button>
  )
}
export default NoticeScreen
```
####2. Modalと、Modalを閉じる関数の作成
```typescript
import React, {useState} from 'react';
import AddCircleIcon from '@material-ui/icons/AddCircle';

function NoticeScreen()  {
  const [open, setOpen] = useState(false);
  return(
    <Button
      variant="contained"
      color="secondary"
      startIcon={<AddCircleIcon />}
      onClick={() => setOpen(true)}
      style={{ marginTop: 30 }}
    >
      新規作成
    </Button>
    {/* Modal */}
    <Modal open={open} onClose={() => setOpen(false)}>
    </Modal>
  )
}
export default NoticeScreen
```

####3. Modalの中身を作成する

```typescript
import { Button, Grid, Typography, Modal, Paper, TextField } from '@material-ui/core';
.
//省略
.
<Modal open={open} onClose={() => setOpen(false)}>
//open={open}は、openがtrueの場合にmodalが開くという意味
<Fade in={open}>
  <Paper style={{ width: modalWidth, position: 'absolute', top: height * 0.1, right: (width - modalWidth - 40) / 2, padding: 20 }}>
    <Typography style={{ marginLeft: 8 }}>タイトル</Typography>
    <TextField
      style={{ margin: 8, paddingBottom: 20 }}
      margin="normal"
      fullWidth
      variant="outlined"
      className="red-border"
    />
    <Typography style={{ marginLeft: 8 }}>コメント</Typography>
    <TextField
      style={{ margin: 8, paddingBottom: 20 }}
      fullWidth
      margin="normal"
      multiline
      rows={4}
      InputLabelProps={{ shrink: true }}
      variant="outlined"
    />
    <Grid container style={{ paddingTop: 30 }} justify="flex-end" direction="row">
      <Grid item>
        <Button
          variant="contained"
          color="secondary"
          onClick={addNewCommentRequest}
          startIcon={<AddCircleIcon />}
        >
          投稿
        </Button>
      </Grid>
    </Grid>
  </Paper>
</Fade>
</Modal>
```

####完全版

```typescript
import React, {useState} from 'react';
import { Button, Grid, Typography, Modal, Paper, TextField } from '@material-ui/core';
import AddCircleIcon from '@material-ui/icons/AddCircle';

function NoticeScreen()  {
  const [open, setOpen] = useState(false);
  return(
    <Button
      variant="contained"
      color="secondary"
      startIcon={<AddCircleIcon />}
      onClick={() => setOpen(true)}
      style={{ marginTop: 30 }}
      >
      新規作成
    </Button>
    {/* Modal */}
    <Modal open={open} onClose={() => setOpen(false)}>
    <Fade in={open}>
      //open={open}は、openがtrueの場合にmodalが開くという意味
      <Paper style={{ width: modalWidth, position: 'absolute', top: height * 0.1,right: (width - modalWidth - 40) / 2, padding: 20 }}>
      <Typography style={{ marginLeft: 8 }}>タイトル</Typography>
      <TextField
      style={{ margin: 8, paddingBottom: 20 }}
      margin="normal"
      fullWidth
      variant="outlined"
      className="red-border"
      />
      <Typography style={{ marginLeft: 8 }}>コメント</Typography>
      <TextField
      style={{ margin: 8, paddingBottom: 20 }}
      fullWidth
      margin="normal"
      multiline
      rows={4}
      InputLabelProps={{ shrink: true }}
      variant="outlined"
      />
      <Grid container style={{ paddingTop: 30 }} justify="flex-end" direction="row">
        <Grid item>
          <Button
          variant="contained"
          color="secondary"
          onClick={addNewCommentRequest}
          startIcon={<AddCircleIcon />}
          >
          投稿
          </Button>
        </Grid>
      </Grid>
    </Paper>
  </Fade>
  </Modal>
  )
}
export default NoticeScreen
```

#6. 終わりに
Material-UIには、これら以外にも便利なコンポーネントはたくさんありますが、今回は私の独断と偏見で便利なMaterial-UIを選び、その使い方について書かせていただきました。今後もMaterial-UIを使っていく中で記事にしたいと感じたら、新たに付け加えていこうと考えています。
不明点や間違っている点があれば、コメントでお知らせください。 

#参考にさせていただいたサイト
[Material-ui公式サイト](https://material-ui.com/)