web-dev-qa-db-ja.com

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

これにアプローチする正しい方法は何ですか?

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関数を作成できますが、それはあまり良いことではありません。同様に、個々の入力のためだけにコンポーネントを作成することもできますが、このようにする方法があるかどうかを見たかったのです。

130
T3db0t

name要素の input のような標準のHTML属性を使用して、入力を識別することをお勧めします。また、状態に別の値を追加することで構成できるため、「total」を状態の個別の値として保持する必要はありません。

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'));
147
Ross Allen

.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を計算するようにしました。)

106
fiatjaf

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

これに似たものをいくつかのアプリで使用していますが、とても便利です。

37

非推奨のソリューション

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

古い回答内容:

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

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

独自のミックスインを実装する

11

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

...
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>
    )
}
5
inostia

Reactという特別なref属性を使用し、onChangegetDOMNode()関数を使用して、Reactイベントの実際のDOMノードと一致させることができます。

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>
  ...
}
4
Janusz Kacalak

@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
manu3569

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

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

これで、各inputname__の値は、このInputFieldname__コンポーネントの個別のインスタンス内で追跡でき、各子コンポーネントを監視するために親の状態で個別の値を作成する必要はありません。

0
Javasamurai