Подтвердить что ты не робот

React.js: Идентификация различных входов с помощью одного обработчикаChange

Любопытно, как правильно подойти к этому:

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 для обработки каждого входа, но это не очень приятно. Аналогично, вы можете создать компонент только для отдельного ввода, но я хотел посмотреть, есть ли способ сделать это так.

4b9b3361

Ответ 1

Я предлагаю придерживаться стандартных атрибутов HTML, таких как name в input Элементы для идентификации ваших входов. Кроме того, вам не нужно сохранять "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'));

Ответ 2

Вы можете использовать метод .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, вычисленный во время рендеринга, так как это рекомендуется делать.)

Ответ 3

Шаблоны событий 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})
}

Я использую что-то похожее на это в нескольких приложениях, и это довольно удобно.

Ответ 4

Устаревшее решение

valueLink/checkedLink устарел от core React, потому что это путает некоторых пользователей. Этот ответ не будет работать, если вы используете недавнюю версию 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

Вы даже можете реализовать свой собственный mixin

Ответ 5

Вы также можете сделать это так:

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

Ответ 6

Вы можете использовать специальный атрибут React под названием ref, а затем сопоставить реальные узлы DOM в событии onChange с помощью функции React getDOMNode():

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

Ответ 7

@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} />;
}

[...]

Ответ 8

Вы можете отслеживать значение каждого дочернего элемента 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 без создания отдельных значений в родительском состоянии для контроля каждого дочернего компонента.

Ответ 9

Я предоставлю действительно простое решение проблемы. Предположим, у нас есть два входа 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.Наш конструктор, который мы хотим сохранить в наших username и password, чтобы мы могли легко получить к ним доступ:

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

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

III. Интересный и "общий" дескриптор только с одним событием onChange основан на этом:

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. Ключевым моментом здесь является то, что имя поля должно соответствовать нашему параметру в состоянии

Надеюсь, я кому-то как-то помог :)

Ответ 10

Привет, улучшил ssorallen ответ. Вам не нужно связывать функцию, потому что вы можете получить доступ к ней без нее.

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'));