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

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

関連記事

MAMPのSQLiteManagerを使用してsqlite3データベースの作成とデータベースファイルの設置

概要 みなさんこんにちはcandleです。今回はsqliteデータベースをMAMPを使用して作成しましょう。 PHP5.3からsqlite3のクラスが充実して、mysqlを使用しなくてもsqliteで …

railsのaws-sdk gemを使ってs3のファイルを削除する

by martinak15 概要 みなさんこんにちはcandleです。今回はs3にアップロードされている画像ファイルをrailsのaws-sdk gemを使用して削除してみたいと思います。 記事中で開 …

Rubyで文字列に含んで欲しくないキーワードがある場合はマッチさせない正規表現

概要 みなさんこんにちはcandleです。今回はRuby主にruby on railsで文字列に含まれて欲しくないキーワードがマッチした場合は通らない正規表現を作りたいと思います。 これは例えばこのよ …

React開発環境構築コマンドcreate-react-appが便利すぎたのでまとめてみた

English 日本語 概要 みなさんこんにちはcandleです。 今回はcreate-react-appコマンドを使ってreactの開発環境の構築とhello worldあたりまでやってみたいと思い …

Chart.js 2.0でy軸の最大値(scales max)と最小値を設定する

概要 みなさんこんにちはcandleです。今回はChart.js2.0でy軸の最大値、最小値を設定する方法を紹介します。 Chart.js 2.0では特に指定しないと自動的に、y軸の最大値を設定してく …


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