3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【React】要素の外をクリックした場合にメニューを閉じる(e.targetとe.currentTargetの違いを利用する)

Posted at

はじめに

レスポンシブ対応でよくある、あるボタンを押すとサイドメニューが展開するというものを実装していた。

そこでメニュー部分をクリックしても閉じないが、メニュー外の部分(背景)をクリックするとサイドメニューが閉じるという機能を実装した際、 JavaScriptのイベントのe.targete.currentTargetの違いについても勉強になったのでまとめておく。

※実装したサンプルコードは以下のCodeSandboxです。ぜひ実際に挙動を試してみてください。

実装の概要

JavaScriptのイベントのe.targete.currentTargetの違いを利用して、メニュー外をクリックしたときのみメニューを閉じるように実装する。

targetcurrentTarget の違いは以下の通り。

実装方法

開閉するサイドメニューを実装する

まずは開閉するサイドメニューを実装する。

Reactの基本的な実装なので、詳細の説明は省略してコードのみ載せる。

import { useState } from "react";

export default function App() {
  const [isShow, setIsShow] = useState(false);

  return (
    <div>
      <button onClick={() => setIsShow(true)}>Menu</button>
      {isShow && (
        <div    // 画面全体を覆う背景 
          style={{
            backgroundColor: "rgba(0, 0, 0, 0.6)",
            position: "fixed",
            top: "0px",
            zIndex: 1,
            width: "100%",
            height: "100%"
          }}
        >
          <div    // メニュー部分
            style={{
              backgroundColor: "white",
              position: "fixed",
              top: "0px",
              zIndex: 1,
              width: "30%",
              height: "100%"
            }}
          >
            <p>Menu</p>
            <ul>
              <li>Top</li>
              <li>Profile</li>
              <li>Blog</li>
            </ul>
            <button onClick={() => setIsShow(false)}>閉じる</button>
          </div>
        </div>
      )}
    </div>
  );
}

メニューの外をクリックした場合はメニューを閉じる

本題の、
・メニューの内、外のどちらをクリックしたか判定する
・メニュー外をクリックした場合はメニューを閉じる
という部分を実装する。

と言っても記述は非常にシンプルで、メニュー画面全体を覆っている(背景となっている) div 要素に、1行追記するのみ。

<div
  // 以下の1行を追記
  onClick={(e) => e.target === e.currentTarget && setIsShow(false)}
  style={{
    backgroundColor: "rgba(0, 0, 0, 0.6)",
    position: "fixed",
    top: "0px",
    zIndex: 1,
    width: "100%",
    height: "100%"
  }}
>

この onClick イベントは、メニューを開いている際に画面いっぱいに表示される背景に付与しているので、 e.target には常にこの div 要素が入ることになる。

それに対して e.currenttarget にはクリックイベントを発生させた要素が入るので、メニュー内をクリックした場合にはメニュー部分の div 要素が、メニュー外(背景)をクリックした場合にはメニュー外(背景)の div が入ることになる。

これにより、クリックしたのが(つまり e.currentTarget が)メニュー外の背景だった場合は、サイドメニューを閉じるという機能を実現している。

さいごに

要素外をクリックした場合にメニューを閉じるという機能の実装方法を検索すると色々な方法が見つかったが、私はこの方法が一番シンプルでしっくり来た。

また今回、 [e.target](http://e.target)e,currentTarget の違いの便利さを学んだと同時に、違いを理解していないと意図しない挙動を引き起こしてしまうかもしれないので気を付けないといけないと思った。

ライブラリを使ってモーダルなどを実装すると、モーダル外をクリックするとモーダルを閉じるようにすることも簡単に出来ることが多いが、あれはどういう方法で実装されているのだろうと少し気になった。

参考記事

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?