【備忘録】日本一わかりやすいReact-Redux講座 実践編 #9 「ネイティブアプリ風ヘッダーを作ろう」

## はじめに
### 概要
この記事は、トラハック氏([@torahack_](https://twitter.com/torahack_))が運営するYoutubeチャンネル『トラハックのエンジニア学習ゼミ【とらゼミ】』の『[日本一わかりやすいReact-Redux講座 実践編](https://www.youtube.com/watch?v=8fNgXnVTULU)』の学習備忘録です。

前回の講座では、Products の 詳細情報ページを作りました。

今回の講座では、Material-UI の ``<AppBar/>``コンポーネントを利用して、ネイティブアプリ風のヘッダーを作成します。

※ 前回記事: [https://qiita.com/ddpmntcpbr/items/1b1acf97a62cd5101884](https://qiita.com/ddpmntcpbr/items/1b1acf97a62cd5101884)


### 動画URL
[ネイティブアプリ風ヘッダーを作ろう【日本一わかりやすいReact-Redux講座 実践編#9】](https://www.youtube.com/watch?v=aTqx0LMPpqI)

### 要点
- Material-UIの``<AppBar>``コンポーネントで、ヘッダーを作成できる。
- Material-UIの``<Badge>``コンポーネントで、アイコンの肩に数字を表示できる。

### 完成系イメージ

**``http://localhost:3000``**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540216/57b1375e-6113-e54c-dd49-d9717a0b31f9.png)

任意のページ上部にヘッダーが表示され、アプリ名ロゴと、各メニューアイコンが表示されています。

メニューアイコンはまだダミーの状態で、クリックしても何も起きません。また、カート右肩のバッジ数も、ダミーの値を表示させています。

メニューアイコンは、ログイン状態のときのみ表示させるため、サインイン画面では表示されません。

**``http://localhost:3000/signin``**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540216/8c8e90b8-fb89-ec4d-5702-c759bc25f38c.png)

## メイン
### ヘッダーを作ろう

今回はとにかくMaterial-UIを用いて、ビューファイルをゴリゴリ書いていくだけです。

ヘッダーはアプリ内の任意のページ上部で表示をさせるため、``App.jsx``を親コンポーネントとして定義していきます。

``src/components/``直下に、新たに``Header``ディレクトリを作り、

- ヘッダー全体のコンポーネントとして``Header.jsx``
- ヘッダー右側のメニューアイコン群を表示するコンポーネントして``HeaderMenu.jsx``

を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540216/c38fd4a8-7dcc-f329-490b-cacc91e9639c.png)

```:実装ファイル(ヘッダー)
1.src/components/Header/Header.jsx
2.src/components/Header/HeaderMenus.jsx
3.src/components/Header/index.js
4.src/App.jsx
```

```jsx:1.src/components/Header/Header.jsx
import React from 'react';
import {makeStyles} from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import logo from "../../assets/img/icons/logo.png";
import { useDispatch, useSelector } from 'react-redux';
import { getSignedIn } from '../../reducks/users/selectors';
import {push} from "connected-react-router"
import {HeaderMenus} from "./index"

const useStyles = makeStyles({
  root: {
    flexGrow: 1,
  },
  menuBar: {
    backgroundColor: "#fff",
    color: "#444",
  },
  toolBar: {
    margin: "0 auto",
    maxWidth: 1024,
    width: "100%"
  },
  iconButtons: {
    margin: "0 0 0 auto"
  }
})

const Header = () => {
  const classes = useStyles();
  const dispatch = useDispatch();
  const selector = useSelector((state)=>state)
  const isSignedIn = getSignedIn(selector)

  return (
    <div className={classes.root}>
      <AppBar position="fixed" className={classes.menuBar}>
        <Toolbar className={classes.toolBar}>
          <img
            src={logo} alt="Torahack Logo" width="128px"
            onClick={()=>dispatch(push("/"))}
          />
          {isSignedIn && (
            <div className={classes.iconButtons}>
              <HeaderMenus />
            </div>
          )}
        </Toolbar>
      </AppBar>
    </div>
  )
}

export default Header
```

- ``<AppBar>``の中に ``<Toolbar>``を記述することで、ヘッダーを実装できます。
- メニューアイコンを表示する``<HeaderMenus>``要素はログイン状態でのみ表示させたいので、``{isSignedIn && ...``で条件分岐しています。


```jsx:2.src/components/Header/HeaderMenus.jsx
import React from "react";
import IconButton from "@material-ui/core/IconButton";
import Badge from "@material-ui/core/Badge";
import ShoppingCartIcon from "@material-ui/icons/ShoppingCart";
import FavoriteBorderIcon from "@material-ui/icons/FavoriteBorder";
import MenuIcon from "@material-ui/icons/Menu"

const HeaderMenu = () => {
  return (
    <>
      <IconButton>
        <Badge badgeContent={3} color="secondary">
          <ShoppingCartIcon />
        </Badge>
      </IconButton>
      <IconButton>
        <FavoriteBorderIcon />
      </IconButton>
      <IconButton>
        <MenuIcon />
      </IconButton>
    </>
  )
}

export default HeaderMenu
```

- return文の中身は1つのHTML要素である必要があるので、``<>...</>``で全体を囲っています。
- ``<Badge>``コンポーネントで Icon をラッピングすることで、Icon の右肩に数値を表示させることができます。現在は、``badgeContent={3}``としてダミーの数値を表示させていますが、最終的にはここに「カートに入れた商品数」が入ります。

```js:3.src/components/Header/index.js
export {default as Header} from "./Header"
export {default as HeaderMenus} from "./HeaderMenus"
```

- エントリーポイントに追加します。

```jsx:4.src/App.jsx
import React from 'react'
import Router from './Router'
import "./assets/reset.css"
import "./assets/style.css"
import {Header} from './components/Header'

const App = () => {
  return (
    <>
      <Header />
      <main className="c-main">
          <Router />
      </main>
    </>
  )
}

export default App;
```

- App.jsxで Header を読み込み、全ページで表示させるようにします。


###　動作確認
「完成系イメージ」と同様のため割愛します。

## さいごに
今回の要点をおさらいすると、

- Material-UIの``<AppBar>``コンポーネントで、ヘッダーを作成できる。
- Material-UIの``<Badge>``コンポーネントで、アイコンの肩に数字を表示できる。

以上です！次回の講座で``<MenuIcon />``の中身を作っていく予定です。

このような学習内容を日々呟いていますので、よろしければTwitter([@ddpmntcpbr](https://twitter.com/ddpmntcpbr))のフォローもよろしくお願いします。