LoginSignup
9
7

More than 5 years have passed since last update.

React + material-uiのPopoverで詰まったこと

Posted at

概要

Popoverを使ってメニューを実装しようとした時に、
メニューを開くタイミングで同時にPopoverのonRequestCloseが走ってしまい、
開いて一瞬で閉じてしまうという事象を解決した話
※ スマホ対応

内容

---↓ ここのメニューアイコン部分を作ってるソース

スクリーンショット 2016-03-06 18.29.56.png

menu.jsx
var MainMenu = React.createClass({
  getInitialState: function() {
    return {
      is_open: false,
      anchorEl: null
    }
  },
  render: function() {
    return (
      <div>
        <IconButton
          className="menu-button"
          onTouchEnd={function() {
            this.setState({
              is_open:true,
              anchorEl:document.getElementsByClassName("menu-button")[0]
            });
          }.bind(this)}
        >
          <MoreVertIcon />
        </IconButton>
        <Popover
          className="popover"
          open={this.state.is_open}
          anchorOrigin={{horizontal: 'left', vertical: 'bottom'}}
          targetOrigin={{horizontal: 'left', vertical: 'top'}}
          style={{
            width:"100px",
            height:"100px",
            padding:"5px"
          }}
          anchorEl={this.state.anchorEl}
          onRequestClose={function() {
            this.setState({is_open:false});
          }.bind(this)}
        >
          <a
            href="http://www.amazon.co.jp/gp/registry/wishlist/"
            target="_blank"
            style={{
              textDecoration:"none",
              margin:"5px"
            }}
          >
            WishList
          </a>
        </Popover>
      </div>
    );
  }
});

こんな風にアイコンを置いて、アイコンをタップするとPopoverでメニューが開くようにしたかったが、
メニューを開こうとするとonRequestCloseが動いてしまう。
原因調査のためにPopoverのonRequestCloseとIconButtonのonTouchEndで event.typeの値がどうなってるのかを見てみる。
ChromeのDevelopperConsoleで見た結果、

メニューが閉じている時

  • IconButton.onTouchEnd: react-touchend
  • PopOver.onRequestClose: click

メニューが開いている時(onRequestCloseのstate変更処理を外して確認)

  • PopOver.onRequestClose: touchstart
  • PopOver.onRequestClose: click

のようにeventが走ってることを確認。
なので、Popover.onRequestCloseを以下のように変更

Popover.onRequestClose.jsx
onRequestClose={function() {
  if (event.type !== "touchstart") return ;
  this.setState({is_open:false});
}.bind(this)}

clickを無視するようにtouchstartのみを見るように変更。
これで想定通りに挙動ができるようになりました。
※ スマホのみを想定してるのでこの形にしましたが、PC等を考慮すると別のやり方が必要になります。

まとめ

想定通りに挙動が噛み合わない時はどんなeventが走っているのかを見ると良さそう。
React+Material-UIはさくっと組み上げるにはかなりいい組み合わせなんじゃないかと思います。

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7