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 …

React NativeでGoogle Chrome上でのデバッグ時に動作が遅くなる場合の対処

English 日本語 概要 みなさんこんにちはcandleです。 今回はReact NativeのデバッグでChromeを使うと シミュレーターの動作が遅くなってしまう問題を対処します。 とは言って …

ruby on railsに最強のwysiwygエディタ、Squireを導入する

概要 みなさんこんにちはcandleです。今回はruby on railsにsquire editorを導入したいと思います。 squireはオープンソースの便利なwysiwygエディタです。 カスタ …

scikit-learnの4つの関数で機械学習などのデータを前処理する

概要 皆んさんこんにちはcandleです。今回はpythonの機械学習ライブラリ『scikit-learn』を使い、データの前処理をしてみます。 scikit-learnでは変換器と呼ばれるものを使い …

CakePHPでhelloworld

概要 CakePHPでプログラミングのお約束helloworldを行いましょう。 helloworldとは動作確認も含めた、一番最初に書くプログラムコードです。 だいたいはhello worldと単純 …


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