概要
みなさんこんにちはcandleです。今回はreactで最もシンプルなドロップダウンメニューを作ってみたいと思います。
前提
- 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のリンクとか。是非挑戦して、使いやすいドロップダウンメニューを作成してみてください。