在ReactJS中向DOM添加唯一列表项

时间:2016-12-15 17:20:44

标签: javascript reactjs

我正在尝试使用React创建一个待办事项列表并且非常接近。当我点击按钮时,我将<li>元素添加到dom中,但是我在输入字段中输入的文本被设置为所有<li> s。我是React的新手,有点困惑。

我怎么能这样做?请参阅代码并链接到codepen:

Codepen live example

var ListContainer = React.createClass({
  getInitialState: function() {
    return {
      numChildren: 0,
      text: null
    };
  },
  onAddChild: function() {
    var inputValue = document.getElementById('itemAdder').value;
    console.log(inputValue);
    this.setState({
      numChildren: this.state.numChildren + 1,
      text: inputValue
    });
  },
  render: function() {
    var children = [];
    for (var i = 0; i < this.state.numChildren; i++) {
      children.push(<Item key={'item_' + i} number={i} text={this.state.text}/>);
    };
    return (
      <List addChild={this.onAddChild}>
        {children}
      </List>
    );
  }
});

var List = React.createClass({
  render: function() {
    return (
      <div id="listContainer">
        <p><input type="text" name="itemAdder" id="itemAdder" /></p>
        <p><button type="button" onClick={this.props.addChild}>Add another item</button></p>
        <ul>
          {this.props.children}
        </ul>
      </div>
    );
  }
});

var Item = React.createClass({
  render: function() {
    var key = this.props.index;
    return (
      <li>{this.props.text}</li>
    );
  }
});

var App = React.createClass({
  render: function() {
    return (
      <div id="main" className="page-wrap">
        <ListContainer />
      </div>
    );
  }
});

ReactDOM.render(
  <App/>,
  document.getElementById('app')
);

2 个答案:

答案 0 :(得分:2)

问题

你非常接近,但问题是当你在render方法中构建子列表时,对于你说的每个项目,value应该等于状态内的文本键。这就是所有<li> s呈现相同值的原因。

<强>解决方案

组件状态的设计不正确。这就是国家应该如何:

getInitialState: function() {
    return {
      numChildren: 0,
      list: [] //this will an array of objects
    };
}

onAddChild方法应该是这样的:

onAddChild: function() {
    var inputValue = document.getElementById('itemAdder').value;
    console.log(inputValue);
    var newList = this.state.list.slice(); //Avoiding state mutation
    newList.push(inputValue)
    this.setState({
      numChildren: this.state.numChildren + 1,
      list: newList
    });
}    

在此之后,当您在render方法中对子数组进行costruct时,会根据for循环的索引关联相应的列表值,如下所示:

for (var i = 0; i < this.state.numChildren; i++) {
  children.push(<Item key={'item_' + i} number={i} text={this.state.list[i]}/>);
}    

答案 1 :(得分:0)

添加新项目时,您不会保存以前添加的值,而是覆盖值本身。

你应该在你的州里保留一系列字符串。

onAddChild: function() {
    var inputValue = document.getElementById('itemAdder').value;

    this.setState({
        items: [...this.state.items, inputValue]
    });
}

numChildren变量不是必需的,因为你可以从items.length

获取它