GatsbyJSにドロワーメニューを追加する

01 27, 2019

ドロワーメニューを追加したい。

カテゴリーをドロワーメニューで表示したい欲が出てきたので実装する。
しかし、ドロワーを1から書くにはJSの理解レベルが足りない。
そこで今回はMaterialUIに泣きついた。

やったこと

  • Material-UIのインストール
  • Headerを実装
  • categorylistを作成

Material-UIのインストール

npm install --save @material-ui/core
npm install --save @material-ui/icons

Headerを実装

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Drawer from '@material-ui/core/Drawer';
import { Link } from 'gatsby';

const styles = {
  list: {
    width: 250,
  },
  root: {
    flexGrow: 1,
  },
  menuButton: {
    marginLeft: -12,
    marginRight: 20,
  },
};

class Header extends Component {
  state = {
    left: false,
  };

  toggleDrawer = (side, open) => () => {
    this.setState({
      [side]: open,
    });
  };

  render () {
    const { classes } = this.props;

    const sideList = (
      <div className={classes.list}>
        <List>
          <Link to="/">
            <ListItem button>
              <ListItemText primary="Home" />
            </ListItem>
          </Link>
          <Link to="/about">
            <ListItem button>
              <ListItemText primary="About" />
            </ListItem>
          </Link>
        </List>
      </div>
    );

    return (
      <div className={classes.root}>
        <AppBar position="relative" color="inherit">
          <Toolbar>
            <IconButton className={classes.menuButton} color="inherit" aria-label="Menu" onClick={this.toggleDrawer('left', true)}>
              <MenuIcon />
            </IconButton>
            <Drawer open={this.state.left} onClose={this.toggleDrawer('left', false)}>
              <div
                tabIndex={0}
                role="button"
                onClick={this.toggleDrawer('left', false)}
                onKeyDown={this.toggleDrawer('left', false)}
              >
                {sideList}
              </div>
            </Drawer>
            <strong>
              <Link to="/" style={{ boxShadow: 'none', textDecoration: 'none', color: 'inherit', fontFamily: 'Montserrat, sans-serif', }}>Post Bank Extra</Link>
            </strong>
          </Toolbar>
        </AppBar>
      </div>
    );
  }
}

Header.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(Header);

これにあとは自分のカテゴリーリストを載せる。

カテゴリーリストの実装

import React from 'react'
import { StaticQuery, graphql } from 'gatsby'
import ListItem from '@material-ui/core/ListItem';
import Button from '@material-ui/core/Button';
import ListItemText from '@material-ui/core/ListItemText';

const CategoryLists = () => (
  <StaticQuery
    query={graphql`
    query{
        allMarkdownRemark(filter: {frontmatter: {pagetype: {eq: "category"}}}) {
          edges{
            node{
              frontmatter{
                categoryslug
                categoryname
              }
            }
          }
        }
      }
    `}

    render={(data) => {
      const posts = data.allMarkdownRemark.edges
      return (
      <div>
      {posts.map(({ node }) => {
          return (
            <ListItem button key={node.frontmatter.categoryslug}>
              <ListItemText primary={node.frontmatter.categoryname}></ListItemText>
            </ListItem>
          )
        })}
      </div>
      );
    }}
  />
)
export default CategoryLists

そして組み込む

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Drawer from '@material-ui/core/Drawer';
import { Link } from 'gatsby';
import CategoryLists from  '../categorylists';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faHome,faUtensils,faQuestion} from '@fortawesome/free-solid-svg-icons'

const styles = {
  list: {
    width: 250,
  },
  root: {
    flexGrow: 1,
  },
  menuButton: {
    marginLeft: -12,
    marginRight: 20,
  },
};

class Header extends Component {
  state = {
    left: false,
  };

  toggleDrawer = (side, open) => () => {
    this.setState({
      [side]: open,
    });
  };

  render () {
    const { classes } = this.props;

    const sideList = (
      <div className={classes.list}>
        <List>
          <Link to="/">
            <ListItem button>
            <FontAwesomeIcon icon={faHome} />
              <ListItemText primary="Home" />
            </ListItem>
          </Link>
          <CategoryLists />
          <Link to="/about">
            <ListItem button>
            <FontAwesomeIcon icon={faQuestion} />
              <ListItemText primary="About" />
            </ListItem>
          </Link>
        </List>
      </div>
    );

    return (
      <div className={classes.root}>
        <AppBar position="relative" color="inherit">
          <Toolbar>
            <IconButton className={classes.menuButton} color="inherit" aria-label="Menu" onClick={this.toggleDrawer('left', true)}>
              <MenuIcon />
            </IconButton>
            <Drawer open={this.state.left} onClose={this.toggleDrawer('left', false)}>
              <div
                tabIndex={0}
                role="button"
                onClick={this.toggleDrawer('left', false)}
                onKeyDown={this.toggleDrawer('left', false)}
              >
                {sideList}
              </div>
            </Drawer>
            <strong>
              <Link to="/" style={{ boxShadow: 'none', textDecoration: 'none', color: 'inherit', fontFamily: 'Montserrat, sans-serif', }}>corydoras</Link>
            </strong>
          </Toolbar>
        </AppBar>
      </div>
    );
  }
}

Header.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(Header);

StaticQueryで実装。便利。

実働

Gatsby よし!動いた!

出来なかったこと

frontmatterにicon設定してリストレンダリングしようとしましたができませんでした。


コリ

コリといいます。奈良県でサラリーマンをしています。GatsbyJSでサイトを作るのが趣味です。