バブリング(イベントの伝播)について
投稿日: 2024年11月17日
毎日お疲れさまです。
バブリングってご存じですか?私は知らないまま先週くらいまで来てて挙動がおかしいで色々調べるとバブリングのせいだと知り、厄介な存在だと感じました。
でも対策は簡単。知ってるか知らないかで時間溶かすかどうかが決まってくると思うので書くことにしました。
特定の要素でイベントが発生した時に、その要素だけでイベントが発生するのではなくその要素の親要素へイベントが伝搬していき、親要素でも同じイベントが発生してしまう現象のことです。
イベントの伝播とも言います。
今思えば、あれはオリジナルアプリ作り始めて間もない頃、子要素のonclickでモーダルを開く処理をしているのに、開かないなんでって苦しんで、親要素のonclickでモーダル閉じる処理をしていたからだったことがありました。
あぁあれか・・となりました。
"use client";
import React from "react";
export const Bubbring: React.FC = () => {
// 親要素のクリックイベントハンドラ
const handleParentClick = (e: React.MouseEvent<HTMLDivElement>) => {
alert("親要素がクリックされました!");
};
// 子要素のクリックイベントハンドラ
const handleChildClick = (e: React.MouseEvent<HTMLDivElement>) => {
alert("子要素がクリックされました!");
};
return (
<div
onClick={handleParentClick}
className="flex size-full justify-center pt-64"
>
<div onClick={handleChildClick} className="">
子要素
</div>
</div>
);
};
こんな感じのコードは普通ないと思いますがあったとします。
クリックします。
子要素をクリックしたんですけど、OKを押すと
親要素まで反応します。これがバブリング(イベントの伝播)です。
e.stopPropagation();
を追加します。
具体的に、追加した例です。
"use client";
import React from "react";
export const Bubbring: React.FC = () => {
// 親要素のクリックイベントハンドラ
const handleParentClick = (e: React.MouseEvent<HTMLDivElement>) => {
alert("親要素がクリックされました!");
};
// 子要素のクリックイベントハンドラ
const handleChildClick = (e: React.MouseEvent<HTMLDivElement>) => {
e.stopPropagation();
alert("子要素がクリックされました!");
};
return (
<div
onClick={handleParentClick}
className="flex size-full justify-center pt-64"
>
<div onClick={handleChildClick} className="">
子要素
</div>
</div>
);
};
これで子要素のイベントは親要素に伝播せず、子要素のイベントのみ発火させることが出来ます。
知ってたらなんてことないんですけど、知らないとドツボにハマります・・
私はハマった側の人です。身代わりにハマっておいたのでこれ読んだ人はハマらないでください。
今回の例のような単純なコードであればわかりやすいのですが、親と子のコンポーネントが別になっていたりするとパッと見ではわからないので厄介です。
私は一回すべてのイベントで発火する関数にconsoleで関数名出力して、どこをクリックしたらどこが発火しているか確認していきました。
そうしないとわからない。自分で書いたけどわからない。エディター上で追っていくより脳死でいけて早いと思いそうしました。地道な作業ですが嫌いじゃないです。
明日は月曜日。一週間頑張りましょう!!
おやすみなさい🎵