- Published on
Reactでコンポーネントの外側がクリックされか判別する
- Authors
- Name
- Ichiki
- @ichiki1023
モーダルやダイアログの UI の場合、モーダルの外側がクリックされたら閉じるような UI って結構見ますよね。
ただそれ実際に React で作るのどうやるんだっけ?と思ったので今回は実際に作ってみることにしました。
結論
コードだけ欲しいという方もいると思うので最終的なコードを最初に置いておきます。 https://codepen.io/ichiki1023/pen/ExaZPJq
class Modal extends React.Component {
constructor(props) {
super(props)
// Refの定義
this.modalRef = React.createRef()
this.handleClickEvent = this.handleClickEvent.bind(this)
}
componentDidMount() {
// EventTargetに全てのClick eventをHandlingできるように登録する
document.addEventListener('click', this.handleClickEvent)
}
componentWillUnmount() {
// click eventがeventListenerに登録されたままになってしまうのでUnmount時にremoveする
document.removeEventListener('click', this.handleClickEvent)
}
handleClickEvent(event) {
if (this.modalRef && this.modalRef.current && !this.modalRef.current.contains(event.target)) {
// ref内にクリックされたeventのDOMが含まれているかを確認する
console.log('Clicked outside!')
}
}
render() {
return (
<div ref={this.modalRef} className={'modal'}>
Modal
</div>
)
}
}
解説
今回の実装において必要なこと
- Ref の定義
- click event を EventTarget に登録
- click された event を見て DOM ノードに含まれているかチェック
ref の定義
Ref は render メソッドで作成された DOM ノードもしくは React の要素にアクセスする方法を提供します
つまり Ref を定義すると現在のコンポーネントの DOM ノードにアクセスできるようになります。
出力するとこんな感じ
console.log(this.modalRef.current) // DOMのnodeを参照するためにcurrent propertyを見ます
↓ Result
"<div class='modal'>Modal</div>"
2. click event を EventTarget に登録
次に現在のコンポーネントで全ての click event を handling できるようにします。 ただの onClick を定義したとしてもコンポーネント内のクリックしか判定できないので EventTarget で画面内の全ての click event を handling できるように登録します。
componentDidMount() {
// EventTarget に全ての Click event を Handling できるように登録する
document.addEventListener('click', this.handleClickEvent)
}
これでどこをクリックしても event を取れるようになりました。
3. click された event を見て Ref に含まれているかチェック
Ref の定義と、全ての Click Event を Handling できるようになったら後は組み合わせるだけです。
ref.current 内に event.target の内容が含まれていない場合はコンポーネントの外側がクリックされたことになるためあとは条件分岐を作ってあげれば完成です。
handleClickEvent (event) {
if (
this.modalRef &&
this.modalRef.current &&
!this.modalRef.current.contains(event.target)
) {
// ref 内にクリックされた event の DOM が含まれているかを確認する
console.log('Clicked outside!')
}
}
まとめ
実際に例を見てみると、案外簡単に実装できたのではないでしょうか。
痒いところに手が届く記事を今後も増やしていければと思います!