如何在React中点击后从列表中删除li元素?

3
    var ListItem = require('./listItem');

    var App = React.createClass({ 
    getInitialState : function(){
        return{
        items : []
    }
    },

    deleteElement: function(){
    },

    addElement : function(){
        this.state.items.push(<ListItem />);
        this.forceUpdate();
    },

    render : function(){
        return (
            <div>
                <ul>{this.state.items.map(function(item,i){return (
                <li>
                    <p onClick='this.deleteElement'>(-)</p>
                    {item}
                </li>
            )})}</ul>
            <p onClick='this.addElement'>(+)</p>
            </div>
        );
    }
    });

目前,我可以使用addElement functionli元素添加到数组中。但是,在单击deleteElement function时,无法弄清楚如何从ul列表中删除特定的li元素。我尝试使用splice(),但没有成功。我是Reactjs的新手,不知道如何以React方式单击删除li元素。
3个回答

3

在你的代码中有几个错误

  1. 不要使用this.forceUpdate();,而应该使用setState

  2. 对于onClick,您应该传递函数的引用而不是字符串'this.addElement'

现在考虑如何从列表中删除元素。您需要将索引this.deleteElement.bind(this, i)传递给deleteElement并按索引从items数组中删除元素,然后设置新状态

var App = React.createClass({
  getInitialState : function(){
    return {
      items : []
    }
  },

  deleteElement: function(index) {
    this.setState({
        items: this.state.items.filter(function (e, i) {
        return i !== index;
      })
    });
  },

  addElement: function() {   
    this.setState({
        items: this.state.items.concat(<ListItem time={ +new Date() } />)
    });
  },

  render: function() {
    var list = this.state.items.map(function(item, i) {
      return <li key={ i }>
        <p onClick={ this.deleteElement.bind(this, i) }>(-)</p>
        <span>{ item }</span>
      </li>
    }, this);

    return <div>
      <ul>{ list }</ul>
      <p onClick={ this.addElement }>(+)</p>
    </div>
  }
});

示例


你的代码很完美,正是我所需要的。但是我的代码与你在fiddle中的代码相同。但是当我点击(-)时,总是删除列表中的最后一个元素。 - user3673959
@Vishwasraj,你能用你的代码创建一个fiddle吗?我会检查它。 - Oleksandr T.
我已经添加了 Fiddle 链接。 - user3673959
@Vishwasraj,它可以工作,你正在使用i - 但在设置新状态后触发重新渲染,您会看到数组的新索引。您需要使用唯一的id - Oleksandr T.

0
在您的地图中,设置deleteElement回调时,请传递当前项目的索引。
<p onClick={ function () { this.deleteElement(i) }  }>(-)</p>

然后,你可以通过切片并排除当前索引来构建一个新的数组。
deleteElement: function(index){
  var items = this.state.items;
  var leftSide = items.slice(0, index);
  var rightSide = items.slice(index + 1, items.length);
  this.setState({ items: leftSide.concat(rightSide) });
}

slicesplice更受欢迎,因为slice不会改变现有的数组。在这里,我们构建一个新的数组,避免任何变异。

如果你使用ES6,这可以稍微简化:

<p onClick={() => this.deleteElement(i) }>(-)</p>

deleteElement: (index) => {
  var items = this.state.items;
  var leftSide = items.slice(0, index);
  var rightSide = items.slice(index + 1, items.length);
  this.setState({ items: [...leftSide, ...rightSide] });
}

在进行此操作时需要注意一个缺点,即 JSX 中围绕 deleteElement 的函数将在每次 render 时重新创建。这会为垃圾回收器带来更多的工作,因为内存中将存在大量未使用的函数指针。


0

这是我会做的事情...

remove(idx) {
  return (event) => {
    // Concatening original items array returns new array - this is important!
    const items = this.state.items.concat();
    items.splice(idx, 1);
    this.setState({ items });
  }
},

render() {
  return (
    <div>
      ...
      <ul>
        { this.state.items.map((item, i) => <Item key={i} remove={this.remove(i)} text={item}  />) }
      </ul>
      ...
    </div>
  );
}

在这里,您正在传递要删除的项目的索引。当然,在渲染中调用函数是没有用的 - 它会在渲染时移除所有项目(实际上,您不应在渲染方法中更改状态)。相反,您返回将在单击时执行的函数。
项目组件可能类似于这样:
const Item = React.createClass({
  render() {
    return (
      <li>
        { this.props.text }
        <span onClick={this.props.remove}>&times;</span>
      </li>
    );
  }
});

这里有一个可用的 fiddle... https://jsfiddle.net/69z2wepo/31009/


{ this.remove(i) }会在点击之前触发remove函数,对吗?处理程序需要传递一个函数。 - Jamie Dixon
不会的。请仔细阅读。this.remove(i)返回一个函数,确实在单击时被调用。看一下Fiddle示例,试着玩一下 :) - Andreyco
1
我明白了。我之前没有注意到remove是一个高阶函数。谢谢你的解释! - Jamie Dixon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接