我正在尝试在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/
删除最后一个输入。
要删除的中间输入,只有2个输入应包含inputarr
数组中的内容。
为什么会这样?如何修复它以删除正确的输入?
答案 0 :(得分:0)
啊,这是一个经典的JavaScript问题。它与您的map
声明有关。您可以详细了解具体详细信息here,但其归结为当点击事件实际触发时,i
的值等于inputarr.length - 1
。要解决此问题,您需要某种方法在每个循环期间保留i
的值。最简单的方法是将click事件更改为:
<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)
});
}
}
如果您不熟悉,可以找到关于闭包的更多信息here
答案 1 :(得分:0)
我认为最好有单独的Input组件和App组件。 然后,您可以创建递增和递减方法,并将它们从App传递到Input组件。我已经制作了一支小笔来展示你如何实现它 我使用了 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')
);