🦁

onClickイベントが親要素に伝播するのを防ぐにはstopPropagationを使うと良さそう

2023/06/01に公開1
import React from "react";

const OnClick: React.FC = () => {
  const parentClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    console.log("parent");
  };

  const childClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    console.log("child");
  };

  return (
    <div onClick={parentClick}>
      <div onClick={childClick}>Click Here</div>
    </div>
  );
};

export default OnClick;

上記のように親要素にも子要素にもonClickイベントを設定していた場合、子要素をクリックしただけで親要素のクリックイベントも呼ばれる。

child
parent

この現象を防ぐためには子要素側でevent.stopPropagation()を呼び出してあげると良い。

import React from "react";

const OnClick: React.FC = () => {
  const parentClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    console.log("parent");
  };

  const childClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    event.stopPropagation(); // 追加
    console.log("child");
  };

  return (
    <div onClick={parentClick}>
      <div onClick={childClick}>Click Here</div>
    </div>
  );
};

export default OnClick;

これにより親要素側のクリックイベントが呼ばれなくなる。

child
GitHubで編集を提案

Discussion

nap5nap5

このような関数を定義してもいいかもです。

定義側

import React from "react";

export const stopPreventEvent = <T extends Event>(e: T): T => {
  e.stopPropagation();
  e.preventDefault();
  return e;
};

export const stopPreventReactEvent = <T extends React.BaseSyntheticEvent>(
  e: T
): T => {
  e.stopPropagation();
  e.preventDefault();
  return e;
};

使用側

import { stopPreventReactEvent } from "@/utils/stopPrevent";
import { Inter } from "next/font/google";

const inter = Inter({ subsets: ["latin"] });

export default function Home() {
  const parentClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    console.log("parent");
  };

  const childClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    stopPreventReactEvent(event);
    console.log("child");
  };

  return (
    <main
      className={`flex min-h-screen flex-col items-center justify-between p-24 ${inter.className}`}
    >
      <div onClick={parentClick}>
        <div onClick={childClick}>Click Here</div>
      </div>
    </main>
  );
}

demo code.
https://codesandbox.io/p/sandbox/demo-0d5fqb?file=%2Fsrc%2Fpages%2Findex.tsx%3A22%2C13

簡単ですが、以上です。