[React]ReactでVue.jsの$emitのような動きをさせたい。
元Vue.js使いなので$emitのようなものを実現したかったです。
どんなものを作るか
こんなのを作ります。
今、映っているボタンを子コンポーネントとして持っている親コンポーネントがconsole.log(...)を表示する処理を持っており、子コンポーネントのボタンを押すことで親コンポーネントの処理が実行されるようにします。
コード例
※今作成している匿名掲示板のコードから一部を抜粋したものを公開するので省略している部分があります。
"use client";
import RightBottomPencilButton01 from "@/components/layouts/RightBottom-PencilButton01";
export default function ButtonList() {
const pencilButtonList = [
{
name: "スレの新規作成",
action: () => {
console.log("わーお"); //処理内容
},
},
{
name: "スレの削除",
action: () => {
console.log("ええやん"); //処理内容
},
},
];
return <RightBottomPencilButton01 ButtonSet={pencilButtonList} />;
}
export default function RightBottomPencilButton01(props: {
ButtonSet: { name: string; action: Function }[];
}) {
const [isMenuOpen, setIsMenuOpen] = useState(false);
return (
<>
<div className="fixed bottom-12 right-12 flex flex-col-reverse items-end gap-4">
// 省略...
{(() => {
return props.ButtonSet.map((el) => {
return (
<MenuItem
isMenuOpen={isMenuOpen}
buttonName={el.name}
//OnClickActionはボタンが押された時に実行される独自のトリガー名
OnClickAction={() => {
//子コンポーネント上で親コンポーネントから渡されたFunctionを実行する
el.action();
}}
/>
);
});
})()}
</div>
</>
);
}
function MenuItem(props: {
buttonName: string;
isMenuOpen: boolean;
OnClickAction: any;
}) {
// ...
return (
<Transition
// ...
>
<div ref={node} className="group relative flex h-14 items-center">
<button
onClick={props.OnClickAction} //ここでクリックされた時に実行するトリガー名を定義する。
className="mx-auto p-3 font-Kiwi-Maru text-lg text-white opacity-0"
>
{props.buttonName}
</button>
<div className="absolute right-0 z-[-1] size-full w-0 rounded-lg border-2 bg-buttonColor01 opacity-0 transition-colors group-hover:bg-buttonHoverColor01"></div>
</div>
</Transition>
);
}
解説
上記のコードは、子コンポーネント内のボタンコンポーネントのクリックによって親コンポーネントで定義した関数を実行する方法を示しています。
ButtonList
コンポーネントでは、RightBottomPencilButton01
コンポーネントに渡すためのボタンのリスト(pencilButtonList
)を定義しています。各ボタンには、name
とaction
というプロパティがあります。name
はボタンの表示名を、action
はボタンがクリックされたときに実行される関数を指定しています。
RightBottomPencilButton01
コンポーネントでは、渡されたボタンのリストをループして表示しています。各ボタンはMenuItem
コンポーネントで表示されます。MenuItem
コンポーネントはボタンの表示名とクリック時の動作を受け取り、それに基づいて表示と動作を行います。
具体的には、MenuItem
コンポーネントのボタンがクリックされると、渡されたOnClickAction
関数が実行されます。この関数は、親コンポーネントで定義した関数(action
)を実行するためのものです。親コンポーネントで定義した関数は、ボタンがクリックされたときに実行したい処理を記述します。
このようにして、子コンポーネント内のボタンコンポーネントのクリックによって親コンポーネントで定義した関数を実行することができます。
(ちなみに解説の部分の文章はNotionのAIに作ってもらいました...スゴイネ)
やっぱReact便利だな~
Vue.jsだと$emitの使い方を覚えないといけなかったり、子コンポーネント上で親コンポーネントから受け取ったpropsの変更をすることが出来なかったりしてたので、Reactすげーって思いました。
Discussion