てくてくあるく

WordPress の テーマ とか プラグイン に ついて 勉強しています

今回は Material-UI を 使って Hello World を 装飾していきます

前回の記事

React を 触ってみた (2) – React + babel + webpack
https://tekuaru.jack-russell.jp/2018/04/29/1711/

React とは 関係ないので スタイルは 自分でどうにかする という人は 次回のパートまで 進んでしまって問題ないです


Material-UI の インストール


(Dir : /var/www/html/)

今回も 作成に必要な パッケージを インストールします

npm install --save-dev material-ui@next @material-ui/icons prop-types

各々のバージョンは 以下のようになりました

"@material-ui/icons": "^1.0.0-beta.43",
"material-ui": "^1.0.0-beta.44",
"prop-types": "^15.6.1",

Drawer を 表示させる


アプリっぽく ヘッダー サイドバー コンテンツ の アセットページが有ったので こちらを参考に 組み込んでいきます

Drawer - Material-UIを参考にさせていただきました。
https://material-ui-next.com/demos/drawers/


/src/component/main.jsx


import React from 'react'

import PropTypes from 'prop-types'

import { withStyles } from 'material-ui/styles'

import AppBar from 'material-ui/AppBar'
import Toolbar from 'material-ui/Toolbar'
import IconButton from 'material-ui/IconButton'
import MenuIcon from '@material-ui/icons/Menu'
import Hidden from 'material-ui/Hidden'
import Drawer from 'material-ui/Drawer'
import Divider from 'material-ui/Divider'
import List, { ListSubheader, ListItem, ListItemText } from 'material-ui/List'

import Typography from 'material-ui/Typography'

const drawerWidth = 240

const styles = theme => ({
  root: {
    flexGrow: 1,
    height: '100vh',
    zIndex: 1,
    overflow: 'hidden',
    position: 'relative',
    display: 'flex',
    width: '100%',
  },
  appBar: {
    position: 'absolute',
    marginLeft: drawerWidth,
    [theme.breakpoints.up('md')]: {
      width: `calc(100% - ${drawerWidth}px)`,
    },
  },
  toolbar: theme.mixins.toolbar,
  navIconHide: {
    [theme.breakpoints.up('md')]: {
      display: 'none',
    },
  },
  drawerPaper: {
    width: drawerWidth,
    [theme.breakpoints.up('md')]: {
      position: 'relative',
    },
  },
  drawerListSubheader: {
    backgroundColor: theme.palette.background.paper,
  },
  content: {
    flexGrow: 1,
    overflowY: 'scroll',
    backgroundColor: theme.palette.background.default,
    padding: theme.spacing.unit * 3,
  },
})

class Main extends React.Component {
  constructor (props) {
    super(props)

    this.state = {
      mobileOpen: false,
    }
  }

  handleToggleDrawer() {
    this.setState({ mobileOpen: !this.state.mobileOpen })
  }

  render() {
    const { classes, theme } = this.props

    const drawer = (
      <div>
        <List>
          <ListSubheader className={classes.drawerListSubheader} component="div">First List</ListSubheader>
          <ListItem button>
            <ListItemText primary="First List Button" />
          </ListItem>
        </List>
        <Divider />
        <List>
          <ListSubheader className={classes.drawerListSubheader} component="div">Second List</ListSubheader>
          <ListItem button>
            <ListItemText primary="Second List Button" />
          </ListItem>
        </List>
      </div>
    )

    return (
      <div className={classes.root}>
        <AppBar className={classes.appBar}>
          <Toolbar>
            <IconButton
              color="inherit"
              aria-label="open drawer"
              onClick={() => this.handleToggleDrawer()}
              className={classes.navIconHide}
            >
              <MenuIcon />
            </IconButton>
            <Typography variant="title" color="inherit" noWrap>
Title
            </Typography>
          </Toolbar>
        </AppBar>
        <Hidden mdUp>
          <Drawer
            variant="temporary"
            anchor={theme.direction === 'rtl' ? 'right' : 'left'}
            open={this.state.mobileOpen}
            onClose={() => this.handleToggleDrawer()}
            classes={{
              paper: classes.drawerPaper,
            }}
            ModalProps={{
              keepMounted: true, // Better open performance on mobile.
            }}
          >
            {drawer}
          </Drawer>
        </Hidden>
        <Hidden smDown implementation="css">
          <Drawer
            variant="permanent"
            open
            classes={{
              paper: classes.drawerPaper,
            }}
          >
            {drawer}
          </Drawer>
        </Hidden>
        <main className={classes.content}>
          <div className={classes.toolbar} />
<h1>Hello World</h1>
        </main>
      </div>
    )

    return <h1>Hello World</h1>
  }
}

Main.propTypes = {
  classes: PropTypes.object.isRequired,
  theme: PropTypes.object.isRequired,
}

export default withStyles(styles, { withTheme: true })(Main)

わかりやすくするために タイトルの部分と コンテンツの部分は インデントを つけていません

サイドバー の 部分は drawer に 切り出してあるので サブタイトルの部分や リストの部分は わかりやすくなっているかなと思います


ページを確認


コンパイルをして ページを確認してみましょう

First React Project
http://react/

ページを 表示させたら 周りに margin が空いていました
というわけで index.html に normalize.css を 読み込ませてしまいましょう


/index.html


<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css">
</head>

無事 表示されました


Material-UI の 変数


Material-UI が 持っている変数は こちらで 確認できます

Default Theme - Material-UI
https://material-ui-next.com/customization/default-theme/


State と Props とは


React における State と Props の違い - Qiita
https://qiita.com/kyrieleison/items/78b3295ff3f37969ab50

上記のほうがわかりやすいので 読んでみてください


propTypes とは


ReactのPropTypes Validator - Qiita
https://qiita.com/park-jh/items/a7dc06a478b944e59222

上記のほうがわかりやすいので 読んでみてください


まとめ


バージョン違いなのか 環境の違いなのか 単純な コピペでは 動かなくて 試行錯誤しましたが
そのおかげで 少し理解が深まったかなって 思います

ほぼほぼ コピペだったので Material-UI の 詳しいことについては 別途 勉強しようと思います

Related Article

いつの間にか Bootstrap 4 が スタンバってるね!!

詳細へ »

Bootstrap 4 alpha 2 で テーマ を 作成してみました!!

詳細へ »

React を 触ってみた (5) – 非同期処理 と Router

詳細へ »