divなどの親要素などがクリック、又はエンターキーを押された時に関数を実行する書き方をまとめました。
どう書くか
lib/pressEnter.ts
const PressEnter = (pressKey: string, callback: () => void) => {
if (pressKey === "Enter") callback();
};
export default PressEnter;
App.tsx
import { useState } from "react";
import PressEnter from "./lib/pressEnter";
export const App = () => {
const [countNum, setCountNum] = useState(0);
return (
<div>
<span
tabIndex={1}
onClick={() => setCountNum(countNum + 1)}
onKeyDown={(event) =>
PressEnter(event.code, () => setCountNum(countNum + 1))
}
>
押すと値が増えるよ
</span>
<p>{countNum}</p>
</div>
);
};
ちょっと例が分かりづらいですが、こんな感じで書くことができます。
event.code
を引数として渡し、どのキーが押されたかを判定して、関数を実行するかどうかを見ています。
event.keyCode
は非推奨のため、こちらを利用しています。
利点
このように記載する理由として、テストを書きやすくするメリットがあるかなと考えてます。以下を分けてテストできるようになるためです。
- エンターキーを押して、関数が実行されるか(PressEnterでテストができる)
- 実行される関数は意図した挙動か
下記は Jest によるテストの例になります。
lib/pressEnter.test.ts
import PressEnter from "./pressEnter";
describe("#PressEnter", () => {
const mockCallback = jest.fn();
describe("when key pressed other than Enter", () => {
PressEnter("KeyA", mockCallback);
expect(mockCallback.mock.calls.length).toBe(0);
});
describe("when Enter key pressed ", () => {
PressEnter("Enter", mockCallback);
expect(mockCallback.mock.calls.length).toBe(1);
});
});
また、複数のcomponent上でエンターキーが押されたら、、、という関数を書く必要がなくなり、DRYに書くことができますね。
今回のコードは codesandbox にまとめてあります。
div 要素などにキーイベントを当てたい、などの場合の参考になればと思います。