如何正确地渲染可移动输入的列表



我正在尝试渲染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/

发生了什么?

  1. 在第一个输入中添加一些东西,将出现第二个。输入3个不同的输入。
  2. 使用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')
);

最新更新