はじめに
Reactでボタンを作るとき、onClick に渡す関数の型として
MouseEventHandler<HTMLButtonElement>か() => voidのどちらを使うか迷いました。
また、次のようなエラーに出会ったことがある人も多いはずです。
型'void'を型'MouseEventHandler<HTMLButtonElement>'に割り当てることはできません。
本記事では、このエラーの原因と、どういう時にどちらを使うべきかを記載します。
ざっくり結論
| 型 | 向いている用途 |
|---|---|
React.MouseEventHandler<HTMLButtonElement> |
イベントオブジェクトが必要なとき |
() => void |
単にクリックで何かしたいとき |
エラーの解消法
エラー
ReactなどのpropsにMouseEventHandler<HTMLButtonElement>を設定していて、下記のように書いた時にエラーが出る。
<MyButton onClick={goToPage(id)} />
解消法
<MyButton onClick={() => goToPage(id)} />
上記のように書くと、goToPage(id)がその場で実行される。
そのため、Propsに渡されるのは「関数」ではなく、実行結果のvoid(何も返ってこない)になる。
void = 実行結果であり、ただの「値」!
MouseEventHandler<HTMLButtonElement>か() => voidのどちらを使うか
①イベントオブジェクトが必要な場合
e.preventDefault() などを使うとき。
// 子
type Props = {
onClick: React.MouseEventHandler<HTMLButtonElement>;
};
// 親
<button onClick={(e) => { e.preventDefault(); }}>Click</button>
②単に何か動かしたい場合
ページ遷移、API実行、など、イベント情報が必要ないとき。
// 子
type Props = {
onClick: () => void;
};
// 親
<button onClick={() => someFunction()}>Click</button>
ちなみに...引数有無の場合
引数あり
<button onClick={() => handleClickWithArg(123)}>Click</button>
引数なし
<button onClick={handleClick}>Click</button>
const handleClick = () => {
console.log("クリックされた!");
};
補足コラム的な:イベントオブジェクトとは?
イベントオブジェクトとは、Reactがクリック時などに自動で渡してくれる情報のまとまり。
中身には次のような情報が入っている。
e.currentTarget // 押されたボタン要素
e.clientX // クリックしたX座標
e.clientY // クリックしたY座標
e.preventDefault() // デフォルト動作の停止
(例)<form>を送信しないようにするときに使用する
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
console.log(e.clientX, e.clientY);
};
この場合、onClickの型はMouseEventHandler<HTMLButtonElement>にしておくと便利。