概要
前回も仕事での備忘録でしたが、今回も仕事で「子コンポーネントでのクリックイベントを違う子コンポーネントに渡す」というタスクがあったので「どうやるんだっけ…」となって上司に教えてもらったのを備忘録として残しておきます。
以下はモーダルと発火させるボタンのコンポーネントを別々に作った例です。
App.js
import {useState} from "react"
import {Block} from "./block"
import {Dialog} from "./dialog"
export default function App() {
// モーダル開閉のstate、初期値はfalse
const [isOpen, setIsOpen] = useState(false)
// モーダルを開くクリックイベント
const openClick = () => {
setIsOpen(true)
}
// モーダルを閉じるクリックイベント
const closeClick = () => {
setIsOpen(false)
}
return (
<div className="App">
<h1>クリックイベント受け渡しテスト</h1>
<Block openClick={openClick} />
<Dialog open={isOpen} closeClick={closeClick} />
</div>
)
}
block.js
export const Block = (props) => {
return (
<div>
<p>ダイアログを下のボタンで開きます</p>
<button onClick={props.openClick}>クリック</button>
</div>
)
}
dialog.js
export const Dialog = (props) => {
return (
<dialog open={props.open}>
<p>ダイアログが開かれました</p>
<button onClick={props.closeClick}>閉じる</button>
</dialog>
)
}
説明
Reactでは、コンポーネント同士のデータのやり取りは通常、propsを介して行われます。
しかし、親コンポーネントと子コンポーネントの関係では、子から親にデータを渡すことはできません。(親から渡されたpropsは子コンポーネントでは読み取り専用)
そのため、このような場合には、親コンポーネントを介してデータを渡す必要があります。具体的には、block.jsxでクリックされたイベントを親コンポーネントのApp.jsxで処理し、その結果をstateに保存し、stateをpropsとしてdialog.jsxにstateの変更を渡すことで実現できます。
- 親コンポーネントの
App.js
にモーダル開閉のstateを作成 -
block.js
に「モーダルを開く」クリックイベントをpropsで渡す -
block.js
でクリックされた内容をstateに保存され、その結果setIsOpen
がtrueになる - trueになった結果が
dailog.jsx
にpropsで渡されモーダルが開く -
dialog.js
に「モーダルを閉じる」クリックイベントもpropsで渡されているので、「閉じる」ボタンでモーダルを閉じる事ができる
demo