ReactでkeyDownイベントを簡単に扱えるHooks「useKey | Rooks」

 React 

 Frontend 

作成日:2022/04/03

この記事のゴール

useKey を使って簡潔に keyDown イベントを扱えるようになる

今回使ったコードはこちらにあります。

React で keydown イベント取得

React アプリでキーボードが押されたときに処理させたい場合は、記述が少し複雑になります。 例として、「Enter」を押したときにカウントアップしていくコードを示します。

こちらの例のコードを使っている人は、branch を main にしてください。(デフォルトです)

import React, { Fragment, useEffect, useState, VFC } from "react";

const App: VFC = () => {
  const [count, setCount] = useState(0);
  const handleKeyDownEnter = (event: KeyboardEvent) => {
    if (event.key === "Enter") {
      setCount(count + 1);
    }
  };

  useEffect(() => {
    document.addEventListener("keydown", handleKeyDownEnter);
    return () => {
      document.removeEventListener("keydown", handleKeyDownEnter);
    };
  }, [count]);

  return <Fragment>Count : {count}</Fragment>;
};

export default App;

注目していただきたいのは、ここ。

useEffect(() => {
  document.addEventListener("keydown", handleKeyDownEnter);
  return () => {
    document.removeEventListener("keydown", handleKeyDownEnter);
  };
}, [count]);

ポイントは、

useEffect の deps に state を指定しなければいけない

アンマウント時にイベントリスナーを除去しないと余計な計算が発生する

時間があったら、アンマウント時の処理を消してみると、動作がすごく重くなることが確認できるのでやってみることをオススメします!

他にも event.key で押されたキーの条件分岐をしたり、気にする部分が多くコードも長くなってしまいます。

useKey

もっとシンプルに keyDown イベント扱いたいと思い、RooksuseKeyを使ってみました。

Rooks と useKey

様々な用途に使える Hooks の宝庫、それがRooksです。

私はまだ useKey 以外使ったことがないのですが、今後他にも見て使ってみようと思っています。

まずはインストールしてみましょう。

npm install --save rooks

基本的な使い方は以下の通りです。

import react, { useRef } from "react";
import { useKey } from "rooks"; // useKeyをimport

// 第一引数にkey、第二引数にイベントハンドラを指定
// targetを指定しなければdocument全体がtargetになる
useKey(["Enter"], handleKewDownEnter);

// useRefを使うことでtargetを指定することが可能
const targetRef = useRef();
useKey(["Enter"], handleKewDownEnter, {
  target: targetRef,
});

これをふまえて先程の例のコードを書き換えてみましょう。

こちらの例のコードを使っている人は、branch を useKey にしてください。

import React, { Fragment, useState, VFC } from "react";
import { useKey } from "rooks";

const App: VFC = () => {
  const [count, setCount] = useState(0);
  const handleKewDownEnter = () => setCount(count + 1);
  useKey(["Enter"], handleKewDownEnter);

  return <Fragment>Count : {count}</Fragment>;
};

export default App;

いかがでしょうか!?

useKeyを使うことでかなりすっきりとしたコードになりますね!

私は、今後 keyDown イベントを扱う際はこれを使っていこうと思います。

参考

React で keydown イベントを取得する方法