使用している教材
Reactに入門した人のためのもっとReactが楽しくなるステップアップコース完全版
Udemyの教材「Reactに入門した人のためのもっとReactが楽しくなるステップアップコース完全版」のセクション3を進めているときに、「表示」ボタンを押しても子コンポーネントが表示されないという問題がありました。
原因は、button要素に使うべきイベントonClickを、間違えてonChangeと書いていたことでした。
この記事では、発生した問題と、その原因であるonClickとonChangeの違いについて解説をしたいと思います。
どんな問題が起きたか
作っていたのは、入力フォームに文字を入力し、「表示」ボタンを押すと、その下に「子コンポーネント」が表示されるというシンプルな機能です。
しかし、表示ボタンを押しても何も反応がない状態でした。
問題のあったコード
実際のコードです。親コンポーネント(App.tsx)が、子コンポーネント(ChildArea.tsx)の表示・非表示を管理しています。
export const ChildArea = (props: {open: boolean}) => {
const {open} = props;
return (
<>
{open ? (
<div>
<p className="bg-blue-500">子コンポーネント</p>
</div>
) : (null)}
</>
)
}
問題があった親コンポーネントのコードです。
import './App.css'
import { useState } from 'react'
import { ChildArea } from './ChildArea';
function App() {
const [text, setText] = useState("");
const [open, setOpen] = useState(false);
const onTextChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setText(e.target.value);
};
const openTextChange = () => {
setOpen(!open);
};
return (
<>
<div className="flex flex-col gap-6">
<div>
<input
value={text}
onChange ={onTextChange}
type="text"
className="border border-gray-300 rounded-md">
</input>
</div>
<div>
<button
onChange={openTextChange} //buttonにonChangeを使っていた
className="rounded-md text-blue-600">
表示
</button>
</div>
<div>
<ChildArea open={open}/>
</div>
</div>
</>
)
}
export default App
原因
button要素はクリックして使うもので、値を変更するという概念がないため、onChangeイベントが発火しなかったのが原因です。
onClickとonChangeの違い
onChange
onChangeイベントは、フォーム要素の値が変更したときに発火するイベントです。
今回のコードでは、入力フォーム(input要素)に文字を入力する度にonTextChangeの関数が呼ばれ、textのstateが更新されます。
onClick
onClickイベントは、要素がクリックされた時に発火するイベントです。
など、ユーザーが直接押したりクリックしたりという操作を行う要素に対して使います。
今回は、表示ボタンを押した時に、子コンポーネントを表示・非表示するという機能を作りたかったので、button要素には、onClickイベントを設定するのが適していました。
修正後のコード
onChangeイベントを、onClickイベントに変更します。
import './App.css'
import { useState } from 'react'
import { ChildArea } from './ChildArea';
function App() {
const [text, setText] = useState("");
const [open, setOpen] = useState(false);
const onTextChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setText(e.target.value);
};
const openTextChange = () => {
setOpen(!open);
};
return (
<>
<div className="flex flex-col gap-6">
<div>
<input
value={text}
onChange ={onTextChange}
type="text"
className="border border-gray-300 rounded-md">
</input>
</div>
<div>
<button
onClick={openTextChange} //onClickに修正する
className="rounded-md text-blue-600">
表示
</button>
</div>
<div>
<ChildArea open={open}/>
</div>
</div>
</>
)
}
export default App
この修正により、表示ボタンをクリックすることでopenTextChange関数が実行されて、openのstateがtrue/falseで切り替わり、子コンポーネントが正しく表示・非表示されるようになりました。

