概要
Popoverを使ってメニューを実装しようとした時に、
メニューを開くタイミングで同時にPopoverのonRequestCloseが走ってしまい、
開いて一瞬で閉じてしまうという事象を解決した話
※ スマホ対応
内容
---↓ ここのメニューアイコン部分を作ってるソース
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を以下のように変更
onRequestClose={function() {
if (event.type !== "touchstart") return ;
this.setState({is_open:false});
}.bind(this)}
clickを無視するようにtouchstartのみを見るように変更。
これで想定通りに挙動ができるようになりました。
※ スマホのみを想定してるのでこの形にしましたが、PC等を考慮すると別のやり方が必要になります。
まとめ
想定通りに挙動が噛み合わない時はどんなeventが走っているのかを見ると良さそう。
React+Material-UIはさくっと組み上げるにはかなりいい組み合わせなんじゃないかと思います。