【问题标题】:Deleting an item in ReactJS在 ReactJS 中删除一个项目
【发布时间】:2016-06-24 10:30:00
【问题描述】:

我是 React 的新手,并制作了一个允许保存搜索的应用。这将提取 JSON,但当前从静态数组 data 提取。我无法从搜索列表中删除搜索。

这是 jsbin:http://jsbin.com/nobiqi/edit?js,output

这是我的删除按钮元素:

var DeleteSearch = React.createClass({
  render: function() {
    return (
      <button onClick="this.props.deleteSearchItem" value={index}><i className="fa fa-times"></i>
        </button>
    );
  }
});

和我的功能

  deleteSearchItem: function(e) {
    var searchItemIndex = parseInt(e.target.value, 10);
    console.log('remove task: %d', searchItemIndex);
    this.setState(state => {
        state.data.splice(searchItemIndex, 1);
        return { data: state.data };
    });
  }

我已经尝试了以下教程,但我不确定从这里可以去哪里。如何删除搜索项?

【问题讨论】:

  • onClick="this.props.deleteSearchItem" 看起来不对。表达式放在大括号之间,就像您在 value={index} 中所做的那样
  • 喜欢onClick={this.props.deleteSearchItem}?我是语法新手,所以很有帮助。
  • 花半个小时去facebook.github.io/react/docs/tutorial.html,然后把整个事情都跑一遍。没有跳过部分,只需按照它所说的从头到尾做。无论您是 Web 开发新手还是 10 多年经验丰富的专业人士,该教程在教您基础知识方面都非常棒,因此您无需再问此类问题。
  • @Mike'Pomax'Kamermans 我确实仔细阅读了它,上面的很多代码都是从文档中编写的。但是我来这里是因为我仍然遇到了麻烦。必须通过文档中的一些功能才能真正理解。
  • 你读过它,还是你做过它?因为只是阅读它并没有遵循教程。如果您按照本教程进行操作,您也会学习 facebook.github.io/react/docs/… 部分,该部分教您如何引用组件函数进行事件处理。

标签: javascript reactjs


【解决方案1】:

让我猜猜,你在找这样的东西吗?

class Example extends React.Component {
    constructor(){
    this.state = {
      data: [
        {id:1, name: 'Hello'},
        {id:2, name: 'World'},
        {id:3, name: 'How'},
        {id:4, name: 'Are'},
        {id:5, name: 'You'},
        {id:6, name: '?'}
      ]
    }
  }

  // shorter & readable 
  delete(item){
    const data = this.state.data.filter(i => i.id !== item.id)
    this.setState({data})
  }

  // or this way, it works as well
  //delete(item){
  //  const newState = this.state.data.slice();
  //    if (newState.indexOf(item) > -1) {
  //    newState.splice(newState.indexOf(item), 1);
  //    this.setState({data: newState})
  //  }
  //}

  render(){
    const listItem = this.state.data.map((item)=>{
        return <div key={item.id}>
        <span>{item.name}</span> <button onClick={this.delete.bind(this, item)}>Delete</button>
      </div>
    })
    return <div>
        {listItem}
    </div>
  }
}

React.render(<Example />, document.getElementById('container'));

在此示例中,请注意我如何绑定 delete 方法并在那里传递新参数。 fiddle

希望对你有帮助。

谢谢

【讨论】:

  • 我怀疑这对于长列表来说非常高效。我的猜测是将 id 作为字符串存储在列表项中,然后检索它的性能更高,也许还有一种更“原生”的方式用 React 做到这一点?
  • @AlexMills 在这种情况下你应该看看 Flux 或 Redux 架构
  • const newState = this.state.data; 不会复制您所在州的数据对象。它只是在newState 中存储对this.state.data 的引用。所以,当你splice() 出一个项目时,你直接修改了this.state.data。那是the wrong way。我只是通过在你的fiddle 的fork 中评论setState 行来证明这一点至于正确的方法,我不知道......这就是我来这里寻找的。​​span>
  • @Vince,是的,你是对的。我应该使用这些选项之一 Array.prototype.slicespread 操作符来复制新的 state
【解决方案2】:

在这里。由于四年后我对 React 有了更多的了解,而且这仍然得到了一些意见,所以我想我会用我现在的做法来更新它。

SavedSearches.js

import React from 'react'
import { SearchList } from './SearchList'

let data = [
    {index: 0, name: "a string", url: 'test.com/?search=string'},
    {index: 1, name: "a name", url: 'test.com/?search=name'},
    {index: 2, name: "return all", url: 'test.com/?search=all'}
  ];

let startingIndex = data.length;

export class SavedSearches extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: '',
            url: '',
            index: startingIndex,
            data: data
        }
        this.deleteSearch=this.deleteSearch.bind(this)
    }
    deleteSearch(deleteThis) {
        console.log(deleteThis);
        let newData = this.state.data.filter( searchItem => searchItem.index !== deleteThis.index )
        this.setState({
            data: newData
        })
    }

    render() {
        return (
            <div className="search-container">
                <SearchList data={this.state.data} onDelete={this.deleteSearch}/>
            </div>
        )
    }
}

在这里,我创建了一个名为deleteSearch 的方法,它接受一个对象作为参数。然后它在this.state.data 数组上运行.filter 以创建一个包含所有不满足条件的项目的新数组。条件检查数据数组中每个对象的 id 是否与参数的 id 匹配。如果是这样,那么它就是被删除的那个。由.filter 创建的新数组设置为名为@9​​87654327@ 的变量,然后我使用newData 数组更新状态。

然后,我将此方法传递给名为 onDelete 的 prop 中的 SearchList 组件。

这个方法也在构造函数中使用.bind()绑定,这样当方法向下传递到组件树时this将引用正确的this

SearchList.js

import React from 'react'
import { SearchItem } from './SearchItem'
export class SearchList extends React.Component {
    render() {
      let searchItems = this.props.data.map((item, i) => {
        return (
          <SearchItem index={i} searchItem={item} url={item.url} onDelete={this.props.onDelete}>
            {item.name}
          </SearchItem>
        );
      });
      return (
        <ul>
          {searchItems}
        </ul>
      );
    }
}

我的deleteSearch 方法只是通过这里的组件树。 SearchList 接收方法作为 props this.props.onDelete 并将其传递给 SearchItem

这里的另一个主要关键是 map 函数中的参数作为道具传递:searchItem={item}。这将允许通过 props 访问整个当前对象;如果你还记得的话,我的deleteSearch 函数将一个对象作为参数。

SearchItem.js

import React from 'react'

export class SearchItem extends React.Component {
    constructor(props) {
        super(props);
        this.handleDelete=this.handleDelete.bind(this)
    }
    handleDelete() {
        this.props.onDelete(this.props.searchItem)
    }
    render() {
      return (
        <li key={this.props.index}> {/* Still getting a console error over this key */}
          <a href={this.props.url} title={this.props.name}>
            {this.props.children}
          </a>
          &nbsp;({this.props.url})
          <button onClick={this.handleDelete} value={this.props.index}><i className="fa fa-times"></i>
          </button>
        </li>
      );
    }
  };

现在我的方法到达了使用它的地方。我创建了一个处理程序方法handleDelete,并在其中使用this.props.onDelete 访问deleteSearch 方法。然后我将使用this.props.searchItem 单击的列表项的对象传递给它。

为了在用户单击时使其工作,我必须添加一个调用我的处理程序方法的onClick 事件侦听器,如下所示:onClick={this.handleDelete}。最后一步是在SearchItem构造方法中绑定this.handleDelete

现在,单击该按钮将从this.state.data 数组中删除该项目。有关如何向数组中添加项目的示例,请参阅我的repository

【讨论】:

    【解决方案3】:

    你在寻找这样的东西吗?

    Todos.js

    import React from 'react'
    import {TodoItem} from "./TodoItem";
    
    export const Todos = (props) => {
    
        let myStyle = {
            minHeight: "70vh",
            margin: "40px auto"
        }
        return (
            <div className="container" style={myStyle}>
                <h3 className="my-3">List</h3>
                {props.todos.length===0? "No records to display":  
                props.todos.map((todo)=>{
                    console.log(todo.sno);
                    return (<TodoItem todo={todo} key={todo.sno} onDelete={props.onDelete}/>   
                    )
                })
                  } 
            </div>
        )
    }
    

    TodoItem.js

    import React from 'react'
    
    export const TodoItem = ({todo, onDelete}) => {
    
        return (
            <>
            <div>
               <h4>{todo.title}</h4>
               <p>{todo.desc}</p>
               <button className="btn btn-sm btn-danger" onClick={()=>{onDelete(todo)}}>Delete</button> 
            </div>
            <hr/> 
            </>
        )
    }
    

    请查看repository,在这里您可以找到添加、删除和列出项目

    【讨论】:

      猜你喜欢
      • 2016-12-08
      • 1970-01-01
      • 1970-01-01
      • 2022-11-30
      • 2020-05-12
      • 1970-01-01
      • 2018-06-29
      • 2021-06-09
      • 2017-08-31
      相关资源
      最近更新 更多