Любопытно, как правильно подойти к этому:
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 для обработки каждого входа, но это не очень приятно. Аналогично, вы можете создать компонент только для отдельного ввода, но я хотел посмотреть, есть ли способ сделать это так.
Ответ 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'));