React.js:1つのonChangeハンドラーでさまざまな入力を識別する


141

これに取り組む正しい方法は何ですか?

var Hello = React.createClass({
getInitialState: function() {
    return {total: 0, input1:0, input2:0};
},
render: function() {
    return (
        <div>{this.state.total}<br/>
            <input type="text" value={this.state.input1} onChange={this.handleChange} />
            <input type="text" value={this.state.input2} onChange={this.handleChange} />
        </div>
    );
},
handleChange: function(e){
    this.setState({ ??? : e.target.value});
    t = this.state.input1 + this.state.input2;
    this.setState({total: t});
}
});

React.renderComponent(<Hello />, document.getElementById('content'));

もちろん、個別のhandleChange関数を作成して、それぞれの入力を処理することもできますが、それはあまり良くありません。同様に、個々の入力のためだけにコンポーネントを作成することもできますが、このような方法があるかどうかを確認したいと思いました。

回答:


162

私のような標準のHTML属性にこだわるお勧めnameinputご入力を識別するための要素。また、「合計」を状態に別の値として保持する必要はありません。これは、状態に他の値を追加することで構成できるためです。

var Hello = React.createClass({
    getInitialState: function() {
        return {input1: 0, input2: 0};
    },
    render: function() {
        const total = this.state.input1 + this.state.input2;

        return (
            <div>{total}<br/>
                <input type="text" value={this.state.input1} name="input1" onChange={this.handleChange} />
                <input type="text" value={this.state.input2} name="input2" onChange={this.handleChange} />
            </div>
        );
    },
    handleChange: function(e) {
        this.setState({[e.target.name]: e.target.value});
    }
});

React.renderComponent(<Hello />, document.getElementById('content'));

3
最初はこれを試みましたが、setState({e.target.name ...が機能しません。これは構文エラーです。obj[e.target.name]を使用して一時オブジェクトを作成し、それにsetStateを設定する必要があります。この種の動作はしますが、状態オブジェクトの更新になんらかの遅延があるようです
T3db0t

1
「遅延の種類」は、requestAnimationFrame(私は想定)中のsetStateの更新なので、その注釈は無視してください
T3db0t

24
@ T3db0tこのES6構文作品:this.setState({ [e.target.name]: e.target.value });
XåpplI'-I0llwlg'I -

2
bindを使用する方が良い方法です。この方法は、divなどの名前プロパティのない要素にonChangeハンドラーをアタッチする場合は機能しません。
ericgrosse

3
@ericgrosseバインドは、多くの不要な関数を作成しているため、この場合は適していません。また、必要に応じて、
data-

106

.bindメソッドを使用して、メソッドのパラメーターを事前に構築できますhandleChange。それは次のようなものです:

  var Hello = React.createClass({
    getInitialState: function() {
        return {input1:0, 
                input2:0};
    },
    render: function() {
      var total = this.state.input1 + this.state.input2;
      return (
        <div>{total}<br/>
          <input type="text" value={this.state.input1} 
                             onChange={this.handleChange.bind(this, 'input1')} />
          <input type="text" value={this.state.input2} 
                             onChange={this.handleChange.bind(this, 'input2')} />
        </div>
      );
    },
    handleChange: function (name, e) {
      var change = {};
      change[name] = e.target.value;
      this.setState(change);
    }
  });

  React.renderComponent(<Hello />, document.getElementById('content'));

totalレンダリング時に計算することをお勧めしますので、これも作成しました。)


13
this.handleChange.bind(...)新しい機能を作成するための簡単なリマインダー。で使用shouldComponentUpdateしている場合、PureRenderMixinまたは類似したものは壊れます。単一の値が変更されると、すべての入力コンポーネントが再レンダリングされます。
ゼミルコ2015年

5
あなたがの実装に変更した場合handleChangehandleChange(name) { return event => this.setState({name: event.target.value}); }、あなたが「同じ」機能を渡すことができ、それが使用して行われますよう(新しい関数を作成しません.bind()その後、あなたは、このような関数を渡すことができます:this.handleChange("input1")
Andreyco

1
setStateの性質として、handChange関数で現在の状態を取得することはできませんが、たとえばthis.state.input1を使用して以前の状態を取得することができるということも重要です。適切なアプローチは、以下のようなコールバックを作成するであろうthis.setState(change, function () { console.log(this.state.input1); );基準:stackoverflow.com/questions/30782948/...
チャーリー・グリーンマン

39

onChangeイベントは、泡...あなたはこのような何かを行うことができますので。

// A sample form
render () {
  <form onChange={setField}>
    <input name="input1" />
    <input name="input2" />
  </form>
}

そして、setFieldメソッドは次のようになります(ES2015以降を使用している場合):

setField (e) {
  this.setState({[e.target.name]: e.target.value})
}

私はいくつかのアプリでこれに似たものを使用しており、かなり便利です。


11

非推奨のソリューション

valueLink/checkedLinkされている非推奨、それは一部のユーザーを混乱されているので、コアから反応します。Reactの最新バージョンを使用している場合、この回答は機能しません。ただし、気に入った場合は、独自に作成することで簡単にエミュレートできます。Inputコンポーネントをます

古い回答内容:

Reactの双方向データバインディングヘルパーを使用すると、達成したいことをはるかに簡単に達成できます。

var Hello = React.createClass({
    mixins: [React.addons.LinkedStateMixin],
    getInitialState: function() {
        return {input1: 0, input2: 0};
    },

    render: function() {
        var total = this.state.input1 + this.state.input2;
        return (
            <div>{total}<br/>
                <input type="text" valueLink={this.linkState('input1')} />;
                <input type="text" valueLink={this.linkState('input2')} />;
            </div>
        );
    }

});

React.renderComponent(<Hello />, document.getElementById('content'));

簡単でしょう?

http://facebook.github.io/react/docs/two-way-binding-helpers.html

独自のミックスインを実装することもできます


状態を設定するためにonchangeをバインドする必要があるのはなぜですか。やっぱりReactJSです!
Junaid Qadir

このソリューションは廃止されていることに注意してください
Philipp

6

次のようにすることもできます:

...
constructor() {
    super();
    this.state = { input1: 0, input2: 0 };
    this.handleChange = this.handleChange.bind(this);
}

handleChange(input, value) {
    this.setState({
        [input]: value
    })
}

render() {
    const total = this.state.input1 + this.state.input2;
    return (
        <div>
            {total}<br />
            <input type="text" onChange={e => this.handleChange('input1', e.target.value)} />
            <input type="text" onChange={e => this.handleChange('input2', e.target.value)} />
        </div>
    )
}

うまくいきませんでした。React開発者ツールを見た。
input1

1
@Gaurravsはい、あなたは正しいです。私は追加する必要が[]周りinputSETSTATEに。これにより、プロパティが動的に割り当てられます
イノスティア

4

Reactと呼ばれる特別な属性を使用し、の関数を使用refしてonChangeイベントの実際のDOMノードを照合できます。ReactgetDOMNode()

handleClick: function(event) {
  if (event.target === this.refs.prev.getDOMNode()) {
    ...
  }
}

render: function() {
  ...
  <button ref="prev" onClick={this.handleClick}>Previous question</button>
  <button ref="next" onClick={this.handleClick}>Next question</button>
  ...
}

少なくとも0.13では、this.refsにはプロパティの設定がありません。
2015年

2
@usagidon- メソッドでprev設定した名前ですrender()
Janusz Kacalak

2
React v0.14以降、実行できるのはだけですevent.target === this.refs.prevfacebook.github.io/react/blog/2015/10/07/...
XåpplI'-I0llwlg'I -

0

@Vigril Disgr4ce

マルチフィールドフォームに関しては、Reactの主要な機能であるコンポーネントを使用することは理にかなっています。

私のプロジェクトでは、少なくとも値のプロパティを受け取るTextFieldコンポーネントを作成し、入力テキストフィールドの一般的な動作を処理します。これにより、値の状態を更新するときにフィールド名を追跡することを心配する必要がなくなります。

[...]

handleChange: function(event) {
  this.setState({value: event.target.value});
},
render: function() {
  var value = this.state.value;
  return <input type="text" value={value} onChange={this.handleChange} />;
}

[...]

0

単一のの値を管理inputする個別のInputFieldコンポーネントを作成することにより、各子の値を追跡できますinput。たとえば、次のInputFieldようになります。

var InputField = React.createClass({
  getInitialState: function () {
    return({text: this.props.text})
  },
  onChangeHandler: function (event) {
     this.setState({text: event.target.value})
  }, 
  render: function () {
    return (<input onChange={this.onChangeHandler} value={this.state.text} />)
  }
})

これで、各子のコンポーネントを監視するために親の状態で個別の値を作成することなくinput、このInputFieldコンポーネントの個別のインスタンス内でそれぞれの値を追跡できます。


0

私は問題の本当に簡単な解決策を提供します。2つの入力がusernameあり、password、ハンドルを簡単で汎用的なものにしたいので、それを再利用して定型コードを記述しないようにします。

I.私たちのフォーム:

                <form>
                    <input type="text" name = "username" onChange={this.onChange} value={this.state.username}/>
                    <input type="text" name = "password" onChange={this.onChange} value={this.state.password}/>
                    <br></br>
                    <button type="submit">Submit</button>
                </form>

私たちは、保存したいII.Ourコンストラクタ、usernamepassword私たちは簡単にアクセスできるように、:

constructor(props) {
    super(props);
    this.state = {
        username: '',
        password: ''
    };

    this.onSubmit = this.onSubmit.bind(this);
    this.onChange = this.onChange.bind(this);
}

III。onChangeイベントが1つだけの興味深い「汎用」ハンドルは、これに基づいています。

onChange(event) {
    let inputName = event.target.name;
    let value = event.target.value;

    this.setState({[inputName]:value});


    event.preventDefault();
}

説明させてください:

1.変更が検出されると、onChange(event)呼び出されます

2.次に、フィールドの名前パラメーターとその値を取得します。

let inputName = event.target.name; ex: username

let value = event.target.value; ex: itsgosho

3. nameパラメーターに基づいて、コンストラクターの状態から値を取得し、値で更新します。

this.state['username'] = 'itsgosho'

4.ここで注意すべきキーは、フィールドの名前が状態のパラメーターと一致する必要があることです

私は誰かを助けたと思います:)


0

状態のキーは、入力フィールドの名前と同じである必要があります。その後、handleEventメソッドでこれを行うことができます。

this.setState({
        [event.target.name]: event.target.value
});

-1

こんにちはソラレンの答えを改善しました。関数にバインドしなくても、入力にアクセスできるため、関数をバインドする必要はありません。

var Hello = React.createClass({
    render: function() {
        var total = this.state.input1 + this.state.input2;
        return (
             <div>{total}<br/>
                  <input type="text" 
                    value={this.state.input1}
                    id="input1"  
                    onChange={this.handleChange} />
                 <input type="text" 
                    value={this.state.input2}
                    id="input2" 
                    onChange={this.handleChange} />
            </div>
       );
   },
   handleChange: function (name, value) {
       var change = {};
       change[name] = value;
       this.setState(change);
   }
});

React.renderComponent(<Hello />, document.getElementById('content'));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.