joppot

コピペで絶対動く。説明を妥協しない

プログラミング

reactで最もシンプルなドロップダウンメニューを作成

投稿日:2018年11月16日 更新日:


概要

みなさんこんにちはcandleです。今回はreactで最もシンプルなドロップダウンメニューを作ってみたいと思います。

前提

  1. Reactの知識がある

準備

以下のコマンドでreactプロジェクトを作成します。

create-react-app hello-menu

src/App.jsを開いて、とりあえずこうしておきます。

import React, { Component } from 'react'

class App extends Component {
  render() {
    return (
      <div>
        <p>hello menu</p>
      </div>
    )
  }
}

export default App

srcフォルダの中にcomponentsフォルダを作ります。

mkdir src/components

src/componentsフォルダにDropDownMenu.jsファイルを作ります。

touch src/components/DropDownMenu.js

これで準備が整いました。

ドロップダウンメニューの作成

src/components/DropDownMenu.jsを開いて、以下を書き込みます。

import React from 'react'

class DropDownMenu extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      listOpen: false,
    }
  }

  toggleList() {
    this.setState(prevState => ({
      listOpen: !prevState.listOpen,
    }))
  }

  handleClickMenu(val) {
    this.setState({
      listOpen: false,
    })
    alert(val)
  }

  render() {
    const { listOpen } = this.state
    return (
      <div style={styles.dropDownMenu}>
        <div onClick={this.toggleList.bind(this)} style={styles.menuButton}>
          menu
        </div>
        {listOpen && (
          <div style={styles.menuBox}>
            <div style={styles.menuContent}>
              <div onClick={this.handleClickMenu.bind(this, 1)}>menu 1</div>
            </div>
            <div style={styles.menuContent}>
              <div onClick={this.handleClickMenu.bind(this, 2)}>menu 2</div>
            </div>
            <div style={styles.lastMenuContent}>
              <div onClick={this.handleClickMenu.bind(this, 3)}>menu 3</div>
            </div>
          </div>
        )}
      </div>
    )
  }
}

const styles = {
  dropDownMenu: {
    position: 'relative',
  },
  menuButton: {
    display: 'inline',
    cursor: 'pointer',
    border: '1px solid black',
    padding: '3px 5px',
  },
  menuBox: {
    position: 'absolute',
    top: '23px',
    width: '120px',
    zIndex: 1,
    cursor: 'pointer',
    border: '1px solid black',
  },
  menuContent: {
    padding: '3px 5px',
    borderBottom: '1px solid black',
  },
  lastMenuContent: {
    padding: '3px 5px',
  },
}

export default DropDownMenu

そしたら、src/App.jsを開いて、このように編集します。

import React, { Component } from 'react'
import DropDownMenu from './components/DropDownMenu'

class App extends Component {
  render() {
    return (
      <div>
        <p>hello menu</p>
        <DropDownMenu />
      </div>
    )
  }
}

export default App

サーバを起動します。

yarn run start

“menu”ボタンを押すとメニューが表示されて、もう一度”menu”ボタンを押すと閉じます。
メニューのリストをクリックするとアラートが表示れ、メニューが閉じます。

メニュー外をクリックして閉じる

“menu”ボタンを押した後、再度閉じるにはもう1度”menu”ボタンを押す必要がありますが、多くのサイトはそれ以外のページをクリックすれば簡単に閉じれるようになっていることが多いです。

これはライブラリを使えば簡単に作ることができます。

yarn add react-onclickoutside

src/components/DropDownMenu.jsを開いて編集します。

import onClickOutside from 'react-onclickoutside'

をファイルのトップに記述します。

新たに関数を作成します。

  handleClickOutside() {
    this.setState({
      listOpen: false,
    })
  }

一番下のexport default DropDownMenu

export default onClickOutside(DropDownMenu)

に変更して終わりです。ブラウザで確認してみてください。メニューを開いた後、外部をクリックするとメニューが閉じますね。

これが完成したコードです。

import React from 'react'
import onClickOutside from 'react-onclickoutside'

class DropDownMenu extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      listOpen: false,
    }
  }

  toggleList() {
    this.setState(prevState => ({
      listOpen: !prevState.listOpen,
    }))
  }

  handleClickMenu(val) {
    this.setState({
      listOpen: false,
    })
    alert(val)
  }

  handleClickOutside() {
    this.setState({
      listOpen: false,
    })
  }

  render() {
    const { listOpen } = this.state
    return (
      <div style={styles.dropDownMenu}>
        <div onClick={this.toggleList.bind(this)} style={styles.menuButton}>
          menu
        </div>
        {listOpen && (
          <div style={styles.menuBox}>
            <div style={styles.menuContent}>
              <div onClick={this.handleClickMenu.bind(this, 1)}>menu 1</div>
            </div>
            <div style={styles.menuContent}>
              <div onClick={this.handleClickMenu.bind(this, 2)}>menu 2</div>
            </div>
            <div style={styles.lastMenuContent}>
              <div onClick={this.handleClickMenu.bind(this, 3)}>menu 3</div>
            </div>
          </div>
        )}
      </div>
    )
  }
}

const styles = {
  dropDownMenu: {
    position: 'relative',
  },
  menuButton: {
    display: 'inline',
    cursor: 'pointer',
    border: '1px solid black',
    padding: '3px 5px',
  },
  menuBox: {
    position: 'absolute',
    top: '23px',
    width: '120px',
    zIndex: 1,
    cursor: 'pointer',
    border: '1px solid black',
  },
  menuContent: {
    padding: '3px 5px',
    borderBottom: '1px solid black',
  },
  lastMenuContent: {
    padding: '3px 5px',
  },
}

export default onClickOutside(DropDownMenu)

まとめ

自分のプロジェクトで利用する時はデザインはもちろんですが、他のライブラリと組み合わせて使うことになるでしょう例えばreact-routerのリンクとか。是非挑戦して、使いやすいドロップダウンメニューを作成してみてください。

スポンサードリンク

「為になったなぁ」と思ったら、シェアお願いします。

-プログラミング
-,

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

memcachedサーバとruby on railsのdalliを使用してセッションを管理する

概要 みなさんこんにちはcandleです。今回はmemcachedサーバを利用してrailsのセッションを管理してみたいと思います。 一般にrailsでセッション管理をしていると、ブラウザのcooki …

wordpressのbogoでサイトで使用する言語を「en-US」から「en」に変更する方法

English 日本語 概要 みなさんこんにちはcandleです。 今回はbogoプラグインのカスタマイズです。bogoはwordpressのサイトを簡単に他言語に対応することができる素晴らしいプラグ …

wordpressのwp_queryでpost投稿の記事一覧を取得する

概要 みなさんこんにちはcandleです。 最近はwordpressの開発を行っており、そこで、試行錯誤したwp_queryを使った記事一覧の取得の仕方を紹介します。wordpressは少し前まで、q …

sphinxでpythonのクラスや関数のドキュメントを自動生成する

概要 みなさんこんにちはcandleです。今回はpythonのSphinxを使ってクラスや関数の説明を自動生成します。 前提 Python3を使って説明しますが、おそらくpython2でも動くと思いま …

fabricでmysqlコマンドを実行する関数を自作する

概要 皆さんこんにちはcandleです。今回はfabricからリモート先のサーバのmysqlを実行するための環境変数と関数を作成したいと思います。 mysqlは一般にmysqlコマンドをログインしてか …


ベンチャー企業のCTOをやってます。大学時代にプログラミングを始め、javaから入門し、C++へて、PHPへと進み、会社ではRailsを使用。自動化が大好きなプログラマー