如何从onClick

时间:2016-06-06 15:47:14

标签: javascript reactjs

我知道这是一个简单的问题,但我是React的新手。

我错过了什么来获取我点击的值的索引?我只是想说,当用户点击删除时,从数组中删除该值。

<!DOCTYPE html>
<html>
<head>
    <title>
        React Practice
    </title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.js"></script>

</head>
    <body>

        <div id="app">
            <!-- This element's contents will be replaced with your component. -->
        </div>


<script type="text/babel">
var MainContainer = React.createClass({
    getInitialState: function(){
      return {
        name: 'JK_MNO',
        friends: [],
        text: ''
      }
    },
    handleChange: function(e){
        this.setState({
            text: e.target.value
        });
    },
    handleSubmit: function(e){
      e.preventDefault();
      if(this.state.text !== '') {
        var nextfriend = this.state.friends.concat([{
          text: this.state.text, id: Date.now()
        }]);
        var nextText = '';
        this.setState({
          friends: nextfriend, text: nextText
        });
      }
    },
    handleDelete: function(e){
      for (var i = this.state.friends.length - 1; i >= 0; i--) {
        this.state.friends[i]
      };
      this.state.friends.splice(i, 1);
      this.setState({
        friends: this.state.friends
      });
    },
    render: function(){
      return (
        <div>
          <h3> Name: {this.state.name} </h3>
          <ShowList friends={this.state.friends} handleDelete={this.handleDelete} />
          <form onSubmit={this.handleSubmit} >
              Enter Friends: <input className="friendInput" onChange={this.handleChange} value={this.state.text} />
            </form> 
        </div>
      );
    }
});

var ShowList = React.createClass({
  render: function() {
    var createFriend = function(friend) {
      return (
        <li key={friend.id}>{friend.text} <button onClick={this.props.handleDelete}>Delete</button> </li>
      );
    };
    return <ul>{this.props.friends.map(createFriend.bind(this))}</ul>;
  }
});

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

4 个答案:

答案 0 :(得分:2)

在数组上进行映射时,数组中正在考虑的当前项的索引是应用于为映射提供的闭包(函数)的第二个参数。

示例:

const arr = ['a', 'b', 'c', 'd'];

arr.map((item, index, arr) => {
    console.log (item, index, arr);
});

//'a' 0 ['a', 'b', 'c', 'd']
//'b' 1 ['a', ...]
//'c' 2 [...]
//'d' 3 [...]

此外,映射的完整数组是第三个arg。

您可以向元素添加“数据索引”属性,然后在单击事件中引用它。

<li 'data-index'={index}>... <li>

handleDelete: function (e) {
    const index = e.currentTarget.dataset.index;

   //do what you need to delete
}

使用您的代码:

<!DOCTYPE html>
<html>
<head>
...
</head>
<body>

...

<script type="text/babel">
var MainContainer = React.createClass({
    getInitialState: ...,
    handleChange: ...,
    handleSubmit: ...,

    //Here's where you are trying to reference index of clicked element
    handleDelete: function (e) {

      //The event object 'e' contains a reference to the clicked
      //element at property 'currentTarget'.
      const clickedEl = e.currentTarget;

      //Setting the 'data-[varname]' property when you create the
      //element in the render method is a safe way to set custom
      //properties you would like to access from a DOM element. Those props
      //are then accessible via the 'dataset' property from the DOM element.
      //Since we set 'data-index' below, we can find the index of the
      //clicked element with clickedEl.dataset.index.
      const clickedIndex = clickedEl.dataset.index;

      //When using React, never act directly on properties of component
      //state. Your previous code:
      //   this.state.friends.splice(i, 1);
      //did that. Instead, make a copy of your state, make changes to
      //that copy, and update state with that copy.

      //Best practice is to try to keep your state as simple as possible,
      //so consider refactoring to simplify your friends state so that it is
      //not an array of objects. But, with current implementation
      //one way might be something like this.
      const friendsCopy = this.state.friends.map(friend => {
          return {
              id: friend.id,
              text: friend.text,
              ...other properties of a friend  
          };

      });

      //You can splice out the clicked friend
      //(or remove some other way)
      friendsCopy.splice(clickedIndex, 1);

      //Set state with copy
      this.setState({
        friends: friendsCopy
      });

    },
    render: function(){
      return (
        <div>
          ... 
        </div>
      );
    }
});

var ShowList = React.createClass({
  render: function() {

    //Create friend is the closure you are providing
    //to map function for friends. Set the second arg
    //to index to reference the index of the friend being
    //considered. You can then safely set a property of 'data-[varname]'
    //on the element to reference index later. By preceding the
    //var name with 'data-', you'll be able to reference the property
    //later via a clean 'dataset' object without risking overwriting some
    //important property on the DOM object called 'varname'. Here I'll use
    //the varname 'index'.
    var createFriend = function(friend, index) {
      return (
        <li key={friend.id}>{friend.text} <button 'data-index'={index} onClick={this.props.handleDelete}>Delete</button> </li>
      );
    };
    return <ul>{this.props.friends.map(createFriend.bind(this))}</ul>;
  }
});

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

希望能稍微清理一下。看起来你正试图在组件上的几个地方直接对this.state进行更改。避免这样做,而是习惯于复制状态 - >更改复制 - >更新状态。尝试阅读React文档,它们非常好。

答案 1 :(得分:0)

生成每个按钮时,您可以为该按钮的ID指定元素在数组中的相应索引。然后你的handleDelete函数必须检查点击的元素ID值,从数组中删除该元素。

这个问题实际上可能与how to remove an item from a list with a click event in ReactJS?

重复

答案 2 :(得分:0)

使用map你可以生成你的组件,然后使用一些ES6语法糖,你可以将每个元素的索引传递给你的点击处理程序,如下所示:

handleDelete: function(e, i) {
  e.preventDefault();
  // Array manipulation
},
render: function() {
    return (
        <div>
            <ul>
              {this.state.users.map((user,i)=> <li onClick={(e) => this.handleDelete(e,i)}>{user}</li>)}
            </ul>
        </div>
    )
}

Demo

答案 3 :(得分:0)

在努力获得以前的一些编译答案之后,我想出了这个简单的方法。

index来自闭包函数,我正在映射数组。我使用数组的副本来避免更改它的当前状态。

这很有效。

<!DOCTYPE html>
<html>
<head>
    <title>
        React Practice: Friends List
    </title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.js"></script>

</head>
    <body>

        <div id="app">
            <!-- This element's contents will be replaced with your component. -->
        </div>


<script type="text/babel">

var MainContainer = React.createClass({
    getInitialState: function(){
      return {
        name: 'JK_MNO',
        friends: [],
        text: ''
      }
    },
    handleChange: function(e){
        this.setState({
            text: e.target.value
        });
    },
    handleSubmit: function(e){
      e.preventDefault();
      if(this.state.text !== '') {
        var nextfriend = this.state.friends.concat([{
          text: this.state.text, id: Date.now()
        }]);
        var nextText = '';
        this.setState({
          friends: nextfriend, text: nextText
        });
      }
    },
    handleDelete: function(e){
        var i = e.target.value;
        var friendsCopy = this.state.friends;
        this.setState(state => {
            friendsCopy.splice(i, 1);
            friends: friendsCopy
        });
    },
    render: function(){
      return (
        <div>
          <h3> Name: {this.state.name} </h3>
          <ShowList friends={this.state.friends} handleDelete={this.handleDelete} />
          <form onSubmit={this.handleSubmit} >
              Enter Friends: <input className="friendInput" onChange={this.handleChange} value={this.state.text} />
            </form> 
        </div>
      );
    }
});

var ShowList = React.createClass({
  render: function() {
    var createFriend = function(friend, index) {
       return (
        <li key={friend.id}>{friend.text} <button onClick={this.props.handleDelete} value={index}>Delete</button> </li>
      );
    };
    return <ul>{this.props.friends.map(createFriend.bind(this))}</ul>;
  }
});

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

    </body>
</html>