ReactでEscキープレスを検出する方法とその処理方法


124

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)}/>
    )
  }
}

これはうまくいくと思いますが、コールバックのようなものになると思います。これを処理するより良い方法はありますか?


このようにする代わりに、アクティブなコンポーネントであるフラックスの実装を保存する必要はありませんか?
Ben Hare

@BenHare:私はまだそれにかなり新しい。Reactへの移行の実現可能性を検討しています。私はフラックスを試したことがないので、あなたは私が解決策のためにフラックスを調べるべきであることを示唆しています。PS:ESCキープレスの検出についてはどうですか?
2016年

5
明確にするために、最初のコードブロックのように、ドキュメントレベルでのキープレス検出を探していますか?または、これは入力フィールド用ですか?どちらでもかまいませんが、答えの作り方がわかりません。たとえば、次は簡単なドキュメントレベルです。codepen.io
Brad Colthurst

文書レベルで結構です:)
Neo

回答:


228

ドキュメントレベルのキーイベント処理を探している場合componentDidMountは、バインドするのが最善の方法です(Brad Colthurstのコードペンの例で示されているように)。

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

潜在的なエラーやメモリリークを防ぐために、アンマウント時にキーイベントリスナーを必ず削除してください。

編集:フックを使用している場合は、このuseEffect構造を使用して同様の効果を生み出すことができます:

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

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

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

  return (   
    <input />
  )
};

6
addEventListenerand の3番目の引数は何removeEventListenerですか?
jhuang 2017年

2
@jhuang developer.mozilla.org/en-US/docs/Web/API/EventTarget/... -することができotions OU useCapture
フリオ・斎藤

1
@jhuang 通常はのように発生しないfocusイベントをキャプチャするかどうかを指定するのは、useCapture引数です。これはには関係ありませんkeydownが、以前はオプションではなかったため、通常IE <9との互換性のために指定されています。
チェイスサンドマン2017年

私はのthis.escFunctionような関数にラップする必要がありましたがfunction() { this.escFunction(event) }、そうでなければ、「キーダウン」なしでページの読み込み時に実行されていました。
M3RS 2017

1
3番目の引数として「false」を含める必要はありません。デフォルトではfalseです。
NattyC

25

あなたはReactkeyCodeからのescape (27)を聞いてみたいと思います:SyntheticKeyBoardEvent onKeyDown

const EscapeListen = React.createClass({
  handleKeyDown: function(e) {
    if (e.keyCode === 27) {
      console.log('You pressed the escape key!')
    }
  },

  render: function() {
    return (
      <input type='text'
             onKeyDown={this.handleKeyDown} />
    )
  }
})

質問のコメントに投稿されたBrad ColthurstのCodePenは、他のキーのキーコードを見つけるのに役立ちます。


15
私はそれの価値がするように見える反応することを追加することだと思いませんonKeyPress押されたキーがESCで、焦点は内側であるときに、イベントを<input type="text" />。そのシナリオでは、使用することができますonKeyDownし、onKeyUpどちらも火の、そして正しい順序で、。
トム

12

機能コンポーネントでこれを実現する別の方法は、次のようにuseEffectand を使用するuseFunctionことです。

import React, { useEffect } from 'react';

const App = () => {


  useEffect(() => {
    const handleEsc = (event) => {
       if (event.keyCode === 27) {
        console.log('Close')
      }
    };
    window.addEventListener('keydown', handleEsc);

    return () => {
      window.removeEventListener('keydown', handleEsc);
    };
  }, []);

  return(<p>Press ESC to console log "Close"</p>);
}

console.logの代わりに、useState何かをトリガーするために使用できます。


7

ReactはSyntheticKeyboardEventを使用してネイティブブラウザーイベントをラップし、このSyntheticイベントは名前付きキー属性を提供します
これは次のように使用できます。

handleOnKeyDown = (e) => {
  if (['Enter', 'ArrowRight', 'Tab'].includes(e.key)) {
    // select item
    e.preventDefault();
  } else if (e.key === 'ArrowUp') {
    // go to top item
    e.preventDefault();
  } else if (e.key === 'ArrowDown') {
    // go to bottom item
    e.preventDefault();
  } else if (e.key === 'Escape') {
    // escape
    e.preventDefault();
  }
};

3
楽しい事実は、あなたは、以下IE9および/またはFirefox 36以上をサポートする必要がある場合e.keyのためEscapeとして戻ってくるEsc#triggered
8月

4

再利用可能なReactフックソリューションの場合

import React, { useEffect } from 'react';

const useEscape = (onEscape) => {
    useEffect(() => {
        const handleEsc = (event) => {
            if (event.keyCode === 27) 
                onEscape();
        };
        window.addEventListener('keydown', handleEsc);

        return () => {
            window.removeEventListener('keydown', handleEsc);
        };
    }, []);
}

export default useEscape

使用法:

const [isOpen, setIsOpen] = useState(false);
useEscape(() => setIsOpen(false))

3
このソリューションでは、onEscape関数を変更できません。useMemoを使用して、onEscapeをuseEffectのdep配列として渡す必要があります
Neo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.