web-dev-qa-db-ja.com

入力要素がReactJS内でフォーカスされているかどうかを検出する

次のような入力要素が現在ReactJSレンダリング関数内でフォーカスされているかどうかを検出するにはどうすればよいですか?

<input type="text" style={searchBoxStyle} placeholder="Search"></input>   

入力ノードがマウントされ、それへの参照がある限り、いつでも次のようなものを実行できます。

const ReactDOM = require('react-dom')

if ( document.activeElement === ReactDOM.findDOMNode(this.refs.searchInput) )

入力要素への参照を追加する必要があります。

<input ref="searchInput" ...

ただし、入力ノードがまだマウントされていない可能性があるため、renderメソッドでこれを実行しないでください。 componentDidUpdatecomponentDidMountなどのライフサイクルメソッドを使用します。

別の方法は、入力フィールド内にfocusおよびblurイベントのイベントリスナーを追加することです。

<input type="text" onFocus={this.onFocus} onBlur={this.onBlur}...

次に、ハンドラーで状態を設定し、renderメソッドでその状態を確認します。

onBlur: function() {
    this.setState({ focused: false })
},
onFocus: function() {
    this.setState({ focused: true })
},
render: function() {
    if ( this.state.focused ) {
        // do something
    }
    <input onFocus={this.onFocus} onBlur={this.onBlur}...
}

これは、ノードがフォーカスまたはブラーされるたびに再レンダリングを呼び出すことに注意してください(しかし、これはあなたが望むものですよね?)

53
David Hellsing

私はデビッドが与えた答えから始めました。そこで彼は2つの方法を説明し、両方とも私のために働きましたが、私は両方について懸念がありました。

  1. 最初のケースでは、いくつかの欠点があるfindDOMNodeを使用します。少なくとも使用は推奨されておらず、アンチパターンと見なされる方法で簡単に実装できます。また、仮想DOMをバイパスしてDOMを直接操作することにより、コードを遅くすることもできます。

  2. 2番目のオプションでは、コンポーネントの状態を作成および管理するだけで、回答が非常に複雑であるように見え、簡単に同期が外れて、コンポーネントが不必要に再レンダリングされる可能性があります。

そこで、私は次の解決策を思いつきました。

if (this.props.id === document.activeElement.id) {
  // your code goes here
}

Davidの答えに対する同じコメントが適用されます。

ただし、入力ノードがまだマウントされていない可能性があるため、renderメソッドでこれを実行しないでください。 componentDidUpdateやcomponentDidMountなどのライフサイクルメソッドを使用します。

利点:

  • 現在のコンポーネントプロパティ(不変の値)を使用します
  • 状態管理を必要としないため、不必要な再レンダリングを引き起こしません
  • dOMの横断を必要としないので、パフォーマンスはそれと同じくらい良いはずです
  • コンポーネント参照を作成する必要はありません

要件:

  • コンポーネントには、チェックするフォーム要素に渡されるidプロパティが必要です(とにかくほとんどの場合)
14
Marcos Abreu