我正在尝试渲染react中的输入列表,并将输入值绑定到数组。我也试图将其列出,以便列表项目可移动。但是,当我从数组中删除项目时,输入项目不会更新我的期望。而不是删除从数组中间删除的输入,而是删除了最后一个输入并保留了中间输入。
var Inputs = React.createClass({
getInitialState: function() {
return {
inputarr: ['']
};
},
render: function() {
var self = this;
return <div>{ this.state.inputarr.map(function (value, i) {
return <div key={i}><input onChange={function (e) {self.onChangeInput(i, e)}}/>
{ i < (self.state.inputarr.length - 1) && <button onClick={function () {self.onRemove(i)}}>x</button>}
</div>;
}) }</div>;
},
onChangeInput: function (i, e) {
this.state.inputarr[i] = e.target.value;
if (this.state.inputarr[this.state.inputarr.length - 1] !== '') {
this.state.inputarr.push('');
}
this.setState({
inputarr: this.state.inputarr.slice(0)
});
},
onRemove: function (i) {
this.state.inputarr.splice(i, 1);
this.setState({
inputarr: this.state.inputarr.slice(0)
});
}
});
ReactDOM.render(
<Inputs/>,
document.getElementById('container')
);
您可以在此小提琴中运行此操作:https://jsfiddle.net/vvd7hex9/1/
发生了什么?
- 在第一个输入中添加一些东西,将出现第二个。输入3个不同的输入。
- 使用X按钮删除第二个输入。
删除了最后一个输入。
我期望发生的事情
中间输入要删除,只有2个输入应包含inputarr
数组中的内容。
为什么会发生这种情况?如何修复它以删除正确的输入?
ahhhh,这是一个经典的JavaScript问题。它与您的map
语句有关。您可以在此处阅读有关特定详细信息的更多信息,但是它归结为当点击事件实际触发时,i
的值等于inputarr.length - 1
。要解决此问题,您需要某种方法来保留每个循环期间i
的值。最简单的方法是将点击事件更改为:
<button onClick={self.onRemove(i)}>x</button>
和更改onRemove
:
onRemove: function (i) {
var self = this;
return function(e) {
self.state.inputarr.splice(i, 1);
self.setState({
inputarr: this.state.inputarr.slice(0)
});
}
}
如果您不熟悉
我认为最好拥有单独的输入组件和应用程序组件。然后,您可以创建增量和减少方法,并将它们从应用程序传递到输入组件。我已经建造了一支笔来展示如何实现它。
我使用 lodash 的一些有用的方法,请看一下它们的工作方式。
https://codepen.io/dagman/pen/oyayyl
代码本身。
class App extends React.Component {
constructor(props) {
super(props);
this.increment = this.increment.bind(this);
this.decrement = this.decrement.bind(this);
this.state = {
quantity: [0],
};
}
increment(value) {
const { quantity } = this.state;
this.setState({
quantity: quantity.concat(_.last(quantity) + 1),
});
}
decrement(el) {
const { quantity } = this.state;
this.setState({ quantity: _.without(quantity, el) })
}
render() {
const inputs = this.state.quantity.map(x => (
<Input
increment={this.increment}
decrement={this.decrement}
key={x}
toDelete={x}
/>
));
return (
<form>
{inputs}
</form>
);
}
}
class Input extends React.Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.onBtnClick = this.onBtnClick.bind(this);
this.state = {
value: '',
shouldIncrementQuantity: true,
};
}
onChange(e) {
const value = e.target.value;
this.setState({ value });
if(value.trim().length > 0 && this.state.shouldIncrementQuantity) {
this.setState({
shouldIncrementQuantity: false,
}, () => this.props.increment());
}
}
onBtnClick(e) {
e.preventDefault();
this.props.decrement(this.props.toDelete);
}
render() {
return (
<p className="input-field">
<input
type="text"
value={this.state.value}
onChange={this.onChange}
/>
<button onClick={this.onBtnClick}>x</button>
</p>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);