Enterキーを押した後にonChangeイベントを呼び出す


204

私はBootstrapが初めてで、この問題に悩まされています。入力フィールドがあり、1桁だけを入力するとすぐに関数from onChangeが呼び出されますが、整数が入力されているときにEnterキーを押すと、この関数が呼び出されます。検証関数でも同じ問題-呼び出しが早すぎます。

var inputProcent = React.CreateElement(bootstrap.Input, {type: "text",
  //bsStyle: this.validationInputFactor(),
  placeholder: this.initialFactor,
  className: "input-block-level",
  onChange: this.handleInput,
  block: true,
  addonBefore: '%',
  ref:'input',
  hasFeedback: true
});

回答:


404

するためによるとドク反応し、あなたは次のように、キーボードイベントを聞くことができonKeyPressたりonKeyUp、ではありませんonChange

var Input = React.createClass({
  render: function () {
    return <input type="text" onKeyDown={this._handleKeyDown} />;
  },
  _handleKeyDown: function(e) {
    if (e.key === 'Enter') {
      console.log('do validate');
    }
  }
});

更新:React.Componentを使用する

これは、同じことを行うReact.Componentを使用するコードです

class Input extends React.Component {
  _handleKeyDown = (e) => {
    if (e.key === 'Enter') {
      console.log('do validate');
    }
  }

  render() {
    return <input type="text" onKeyDown={this._handleKeyDown} />
  }
}

これがjsfiddleです。

更新2:機能コンポーネントを使用する

const Input = () => {
  const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      console.log('do validate')
    }
  }

  return <input type="text" onKeyDown={handleKeyDown} />
}

2
また、検証プロセスをonBlurイベントにバインドする必要もあります。
2015

5
:同じ入力テキストを参照して、よりコンパクトな方法で解決<input ref='reference' onKeyPress={(e) => {(e.key === 'Enter' ? doSomething(this.refs.reference.value) : null)}} />
musemind

5
@musemind実際には、を使用する必要はありませんref<input onKeyPress={e => doSomething(e.target.value)}十分なものです。
2016

4
@musemindインライン関数の代わりにクラスメソッドを使用するポイントonKeyPressは、トリガーされるたびに新しい関数を作成しないようにすることです。微妙なパフォーマンスの向上です。
2016

1
付属のフィドルはもう機能していません。チェックしてください、とにかくいい答えです
Pardeep Jain 2017

52

入力フィールドでonKeyPressを直接使用できます。onChange関数は、入力フィールドが変更されるたびに状態値を変更し、Enterキーが押された後、関数search()を呼び出します。

<input
    type="text"
    placeholder="Search..."
    onChange={event => {this.setState({query: event.target.value})}}
    onKeyPress={event => {
                if (event.key === 'Enter') {
                  this.search()
                }
              }}
/>

この答えは、上記の受け入れられた答えではなく、私にとってはうまくいきます。
karthik shankar 2018年

重いフォームがある場合は、renderメソッドの外部に関数を作成し、それを参照として渡すことをお勧めします。onKeyPress={this.yourFunc}そうしないと、レンダリングごとに太い矢印の関数が再作成されます。
Viktor

これは、onKeyPressイベントが入力および親のケースに対しても書き込まれる場合に機能します。ありがとう。
Naveen Kumar PG

またはonKeyPress={event => event.key === 'Enter' && this.search()}
camden_kid

24

フォームコントロール(入力)にフォーカスが置かれているときにEnterキーを押すと、通常submit、フォーム自体(入力ではない)で(onSubmit)イベントがトリガーされるthis.handleInputため、フォームにonSubmitをバインドできます。

または、フォーカスが削除されたときに発生するblur(onBlur)イベントにバインドすることもできますinput(たとえば、フォーカスを取得できる次の要素にタブ移動する)。


3
これはを使用するよりもはるかにクリーンですonKeyPress
Blackus

1
ターゲットが違うevent.target.valueので利用できないと
思った

@Izkataあなたが言うことは絶対に正しいです。私の答えは、コントローラーhandleInputメソッドで物事を処理する別の方法を必要とするかもしれません。私の回答に従って行うことは、ユーザーが入力に焦点を当てながらEnterキーを押したときと、submitボタン/入力をアクティブにするときの両方をカバーします。
Luca

では、ほとんどの状況でウェブに何のフォーム、単に入力、この答えは、ユースケースの大半には関係ありませんので、私見ではありませんアプリ
VSYNC

@vsyncそれは大多数には関係ないかもしれませんが、それでも部分的には有効です-そして間違いなく間違っていません、私はそれは反対投票の価値があるとは思いませんか?
Luca、

8

使用できます event.key

function Input({onKeyPress}) {
  return (
    <div>
      <h2>Input</h2>
      <input type="text" onKeyPress={onKeyPress}/>
    </div>
  )
}

class Form extends React.Component {
  state = {value:""}

  handleKeyPress = (e) => {
    if (e.key === 'Enter') {
      this.setState({value:e.target.value})
    }
  }

  render() {
    return (
      <section>
        <Input onKeyPress={this.handleKeyPress}/>
        <br/>
        <output>{this.state.value}</output>
      </section>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById("react")
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>


5

React users、これが完全性のための答えです。

Reactバージョン16.4.2

キーストロークごとに更新するか、送信時にのみ値を取得する必要があります。コンポーネントにキーイベントを追加することは機能しますが、公式ドキュメントで推奨されている代替手段があります。

制御されているコンポーネントと制御されていないコンポーネント

制御された

ドキュメントから-フォームと制御されたコンポーネント

HTMLでは、input、textarea、selectなどのフォーム要素は通常、独自の状態を維持し、ユーザー入力に基づいてそれを更新します。Reactでは、変更可能な状態は通常、コンポーネントの状態プロパティに保持され、setState()でのみ更新されます。

Reactステートを「単一の真の情報源」にすることで、2つを組み合わせることができます。次に、フォームをレンダリングするReactコンポーネントは、後続のユーザー入力でそのフォームで発生する動作も制御します。このようにReactによって値が制御される入力フォーム要素は、「制御されるコンポーネント」と呼ばれます。

制御されたコンポーネントを使用する場合、値を変更するたびに状態を更新しておく必要があります。これを行うには、イベントハンドラーをコンポーネントにバインドします。ドキュメントの例では、通常はonChangeイベントです。

例:

1)コンストラクターのイベントハンドラーをバインドします(状態は保持されます)

constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
}

2)ハンドラー関数を作成する

handleChange(event) {
    this.setState({value: event.target.value});
}

3)フォーム送信関数を作成します(値は状態から取得されます)

handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
}

4)レンダリング

<form onSubmit={this.handleSubmit}>
    <label>
      Name:
      <input type="text" value={this.state.value} onChange={this.handleChange} />
    </label>
    <input type="submit" value="Submit" />
</form>

制御されたコンポーネントを使用する場合handleChange、適切な状態を更新して維持するために、関数が常に起動されます。状態は常に更新された値を持ち、フォームが送信されると、値は状態から取得されます。フォームが非常に長い場合は、すべてのコンポーネントの関数を作成するか、すべてのコンポーネントの値の変更を処理する単純なものを作成する必要があるため、これは欠点かもしれません。

制御されていない

ドキュメントから-非制御コンポーネント

ほとんどの場合、制御されたコンポーネントを使用してフォームを実装することをお勧めします。制御されたコンポーネントでは、フォームデータはReactコンポーネントによって処理されます。代替手段は、フォームデータがDOM自体によって処理される非制御コンポーネントです。

状態の更新ごとにイベントハンドラーを作成する代わりに、制御されていないコンポーネントを作成するには、refを使用してDOMからフォームの値を取得します。

ここでの主な違いは、onChange関数を使用するのではなくonSubmit、フォームを使用して値を取得し、必要に応じて検証することです。

例:

1)イベントハンドラーをバインドし、コンストラクターの入力への参照を作成します(状態に保持される値はありません)

constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.input = React.createRef();
}

2)フォーム送信関数を作成します(値はDOMコンポーネントから取得されます)

handleSubmit(event) {
    alert('A name was submitted: ' + this.input.current.value);
    event.preventDefault();
}

3)レンダリング

<form onSubmit={this.handleSubmit}>
    <label>
      Name:
      <input type="text" ref={this.input} />
    </label>
    <input type="submit" value="Submit" />
</form>

制御されていないコンポーネントを使用する場合、handleChange関数をバインドする必要はありません。フォームが送信されると、値はDOMから取得され、この時点で必要な検証が行われます。入力コンポーネントのハンドラー関数も作成する必要はありません。

あなたの問題

今、あなたの問題について:

...整数が入力されたときにEnterキーを押すと呼び出されるようにしたい

これを実現したい場合は、制御されていないコンポーネントを使用してください。必要がない場合は、onChangeハンドラを作成しないでください。enterキーは、フォームを提出するとhandleSubmit機能が起動されます。

必要な変更:

要素のonChange呼び出しを削除します

var inputProcent = React.CreateElement(bootstrap.Input, {type: "text",
    //    bsStyle: this.validationInputFactor(),
    placeholder: this.initialFactor,
    className: "input-block-level",
    // onChange: this.handleInput,
    block: true,
    addonBefore: '%',
    ref:'input',
    hasFeedback: true
});

フォーム送信を処理し、入力を検証します。フォーム送信関数の要素から値を取得して、検証する必要があります。コンストラクタで要素への参照を作成してください。

  handleSubmit(event) {
      // Get value of input field
      let value = this.input.current.value;
      event.preventDefault();
      // Validate 'value' and submit using your own api or something
  }

非制御コンポーネントの使用例:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    // bind submit function
    this.handleSubmit = this.handleSubmit.bind(this);
    // create reference to input field
    this.input = React.createRef();
  }

  handleSubmit(event) {
    // Get value of input field
    let value = this.input.current.value;
    console.log('value in input field: ' + value );
    event.preventDefault();
    // Validate 'value' and submit using your own api or something
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" ref={this.input} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

ReactDOM.render(
  <NameForm />,
  document.getElementById('root')
);

3

このような小さなラッパー関数を書くこともできます

const onEnter = (event, callback) => event.key === 'Enter' && callback()

次に、入力でそれを消費します

<input 
    type="text" 
    placeholder="Title of todo" 
    onChange={e => setName(e.target.value)}
    onKeyPress={e => onEnter(e, addItem)}/>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.