1. ホーム
  2. javascript

[解決済み] ReactでEscキー押下を検出する方法とその対処法

2022-04-22 06:45:36

質問

reactjsでEscキー入力を検出するにはどうすればよいですか?jqueryと似たようなものです

$(document).keyup(function(e) {
     if (e.keyCode == 27) { // escape key maps to keycode `27`
        // <DO YOUR WORK HERE>
    }
});

検出されたら、その情報をコンポーネントの下に渡したい。3つのコンポーネントがあり、そのうち最後のアクティブなコンポーネントは、エスケープキーが押されたときに反応する必要があります。

コンポーネントがアクティブになったときに登録するようなものを考えていたのですが

class Layout extends React.Component {
  onActive(escFunction){
    this.escFunction = escFunction;
  }
  onEscPress(){
   if(_.isFunction(this.escFunction)){
      this.escFunction()
   }
  }
  render(){
    return (
      <div class="root">
        <ActionPanel onActive={this.onActive.bind(this)}/>
        <DataPanel onActive={this.onActive.bind(this)}/>
        <ResultPanel onActive={this.onActive.bind(this)}/>
      </div>
    )
  }
}

そしてすべてのコンポーネントに

class ActionPanel extends React.Component {
  escFunction(){
   //Do whatever when esc is pressed
  }
  onActive(){
    this.props.onActive(this.escFunction.bind(this));
  }
  render(){
    return (   
      <input onKeyDown={this.onActive.bind(this)}/>
    )
  }
}

これで動くと思いますが、コールバックのような形になるかと思います。何か良い処理方法はないでしょうか?

どのように解決するのですか?

もし、ドキュメントレベルのキーイベントを処理したいのであれば、以下のようにバインドしてください。 componentDidMount がベストな方法です(例として Brad Colthurstのcodepenの例 ):

class ActionPanel extends React.Component {
  constructor(props){
    super(props);
    this.escFunction = this.escFunction.bind(this);
  }
  escFunction(event){
    if (event.key === "Escape") {
      //Do whatever when esc is pressed
    }
  }
  componentDidMount(){
    document.addEventListener("keydown", this.escFunction, false);
  }
  componentWillUnmount(){
    document.removeEventListener("keydown", this.escFunction, false);
  }
  render(){
    return (   
      <input/>
    )
  }
}

エラーやメモリリークの可能性を防ぐため、アンマウント時にキーイベントのリスナーを必ず削除することに注意してください。

EDIT: フックを使用する場合は、以下のようにします。 useEffect という構造で、同様の効果を得ることができます。

const ActionPanel = (props) => {
  const escFunction = useCallback((event) => {
    if (event.key === "Escape") {
      //Do whatever when esc is pressed
    }
  }, []);

  useEffect(() => {
    document.addEventListener("keydown", escFunction, false);

    return () => {
      document.removeEventListener("keydown", escFunction, false);
    };
  }, []);

  return (   
    <input />
  )
};