列表项没有正确删除(反应)

Posted

技术标签:

【中文标题】列表项没有正确删除(反应)【英文标题】:list items are not deleting properly (React) 【发布时间】:2018-09-09 22:01:36 【问题描述】:

感谢您对我的笔记应用程序的帮助。假设我的笔记列表上有 3 个笔记。我想删除列表顶部的注释。无论我尝试删除哪一个,总是首先删除列表最底部的任何一个音符。我检查了 React 控制台,应用组件状态中的 notes 数组显示它已正确删除。但在实际视图本身中,它不是。如何获取它以便删除我选择的确切注释?

    class App extends Component 
        constructor(props) 
            super(props);
            this.state = 
                notes: [],
                title: "",
                details: ""
            
            this.updateTitle = this.updateTitle.bind(this);
            this.updateDetails = this.updateDetails.bind(this);
            this.submitHandler = this.submitHandler.bind(this);
            this.deleteHandler = this.deleteHandler.bind(this);

        

        updateTitle(event) 
            this.setState( title: event.target.value );
        

        updateDetails(event) 
            this.setState( details: event.target.value );
        

        submitHandler(e) 
            e.preventDefault();
            if (!this.state.title.length || !this.state.details.length) 
                return;
            

            const newNote = 
                newTitle: this.state.title,
                newDetails: this.state.details
            
            this.setState(prevState => (
                notes: prevState.notes.concat(newNote),
                title: "",
                details: ""
            ))
        

        deleteHandler(id) 
            this.setState(prevState => (
                notes: prevState.notes.filter((el)=> el !== id)
            ))
        

        render() 
            return (
                <div className="container">
                    <h1 className="title">React Notes App</h1>
                    <NoteForm
                        titleValue=this.state.title
                        detailsValue=this.state.details
                        titleHandle=this.updateTitle
                        detailsHandle=this.updateDetails
                        onSubmit=this.submitHandler
                    />
                    <div className="entry-section">
                        this.state.notes.map((note,i) => (
                            <NoteEntry
                                key=i
                                title=note.newTitle
                                details=note.newDetails
                                deleteNote=this.deleteHandler.bind(this,note) 
                            />
                        ))
                    </div>
                </div>
            );
        
    

const NoteForm = (props) => 
  return (
    <div>
      <form className="form-section">
        <input
          className="title-input"
          type="type"
          placeholder="Title"
          value=props.titleValue
          onChange=props.titleHandle
        />
        <br />
        <textarea
          className="details-input"
          cols="20"
          rows="3"
          placeholder="Details"
          value=props.detailsValue
          onChange=props.detailsHandle
          />
        <br />
        <button
          className="input-button"
          onClick=props.onSubmit
        >Add Note</button>
      </form>
    </div>
  )


        class NoteEntry extends Component 
          constructor(props) 
            super(props);
            this.state = 
              display: false,
              editing: false,
              editTitle: this.props.title,
              editDetails: this.props.details
            
            this.displayToggle = this.displayToggle.bind(this);
            this.edit = this.edit.bind(this);
            this.save = this.save.bind(this);
          

          displayToggle() 
            this.setState(prevState => (
              display: !prevState.display
            ))
          

          edit() 
            this.setState(
              editing: true
            )
          

          save() 
            let titleVal = this.refs.updateTitle.value;
            let detailsVal = this.refs.updateDetails.value;
            this.setState(
              editTitle: titleVal,
              editDetails: detailsVal,
              editing: false
            )
          

          render() 
            return (
              <div className="entry">
                <div className="entry-header" onClick=this.state.editing ? null : this.displayToggle>
                  this.state.editing ? (
                    <input ref="updateTitle" className="edit-title" type="text" defaultValue=this.state.editTitle />
                  ) : (
                      <h2 className="entry-title">this.state.editTitle</h2>
                    )
                  <p className="timestamp">this.displayTime</p>
                </div>
                <hr />
                <div className="entry-content " + (!this.state.display ? "hide-details" : null)>
                  this.state.editing ? (
                    <textarea ref="updateDetails" className="edit-details" cols="10" rows="2" defaultValue=this.state.editDetails></textarea>
                  ) : (
                      <p className="details">this.state.editDetails</p>
                    )
                  <div className="entry-buttons">
                    this.state.editing ? (
                      <button className="save" onClick=this.save>Save</button>
                    ) : (
                        <button className="edit" onClick=this.edit>Edit</button>
                      )
                    
                    <button className="delete" onClick=this.props.deleteNote>Delete</button>
                  </div>
                </div>
              </div>
            )
          
        

【问题讨论】:

【参考方案1】:

使用index 作为您的key 会发生此错误。 React 使用key 属性来跟踪列表中的元素。当您从数组的中间删除一个元素时,索引不会自行删除,而是会重新排列,最后一个索引会消失。这就是为什么数组中的最后一个元素总是被删除的原因。

对于这个解决方案,我提供了注释的title 作为key,但这可能并不总是唯一的。使用生成的键或字段组合作为键会更好

class NoteEntry extends React.Component 
  constructor(props) 
    super(props);
    this.state = 
      display: false,
      editing: false,
      editTitle: this.props.title,
      editDetails: this.props.details
    
    this.displayToggle = this.displayToggle.bind(this);
    this.edit = this.edit.bind(this);
    this.save = this.save.bind(this);
  

  displayToggle() 
    this.setState(prevState => (
      display: !prevState.display
    ))
  

  edit() 
    this.setState(
      editing: true
    )
  

  save() 
    let titleVal = this.refs.updateTitle.value;
    let detailsVal = this.refs.updateDetails.value;
    this.setState(
      editTitle: titleVal,
      editDetails: detailsVal,
      editing: false
    )
  

  render() 
    return (
      <div className="entry">
        <div className="entry-header" onClick=this.state.editing ? null : this.displayToggle>
          this.state.editing ? (
            <input ref="updateTitle" className="edit-title" type="text" defaultValue=this.state.editTitle />
          ) : (
              <h2 className="entry-title">this.state.editTitle</h2>
            )
          <p className="timestamp">this.displayTime</p>
        </div>
        <hr />
        <div className="entry-content " + (!this.state.display ? "hide-details" : null)>
          this.state.editing ? (
            <textarea ref="updateDetails" className="edit-details" cols="10" rows="2" defaultValue=this.state.editDetails></textarea>
          ) : (
              <p className="details">this.state.editDetails</p>
            )
          <div className="entry-buttons">
            this.state.editing ? (
              <button className="save" onClick=this.save>Save</button>
            ) : (
                <button className="edit" onClick=this.edit>Edit</button>
              )
            
            <button className="delete" onClick=this.props.deleteNote>Delete</button>
          </div>
        </div>
      </div>
    )
  


const NoteForm = (props) => 
  return (
    <div>
      <form className="form-section">
        <input
          className="title-input"
          type="type"
          placeholder="Title"
          value=props.titleValue
          onChange=props.titleHandle
        />
        <br />
        <textarea
          className="details-input"
          cols="20"
          rows="3"
          placeholder="Details"
          value=props.detailsValue
          onChange=props.detailsHandle
          />
        <br />
        <button
          className="input-button"
          onClick=props.onSubmit>
          Add Note
        </button>
      </form>
    </div>
  )



class App extends React.Component 
  constructor(props) 
      super(props);
      this.state = 
          notes: [],
          title: "",
          details: ""
      
      this.updateTitle = this.updateTitle.bind(this);
      this.updateDetails = this.updateDetails.bind(this);
      this.submitHandler = this.submitHandler.bind(this);
      this.deleteHandler = this.deleteHandler.bind(this);

  

  updateTitle(event) 
    this.setState( title: event.target.value );
  

  updateDetails(event) 
    this.setState( details: event.target.value );
  

  submitHandler(e) 
    e.preventDefault();
    if (!this.state.title.length || !this.state.details.length) 
        return;
    

    const newNote = 
        newTitle: this.state.title,
        newDetails: this.state.details
    
    this.setState(prevState => (
        notes: prevState.notes.concat(newNote),
        title: "",
        details: ""
    ))
  

  deleteHandler(id) 
    this.setState(prevState => (
        notes: prevState.notes.filter((el)=> el !== id)
    ))
  

  render() 
    return (
        <div className="container">
            <h1 className="title">React Notes App</h1>
            <NoteForm
                titleValue=this.state.title
                detailsValue=this.state.details
                titleHandle=this.updateTitle
                detailsHandle=this.updateDetails
                onSubmit=this.submitHandler
            />
            <div className="entry-section">
                this.state.notes.map((note,i) => (
                    <NoteEntry
                        key=note.newTitle
                        title=note.newTitle
                        details=note.newDetails
                        deleteNote=this.deleteHandler.bind(this,note) 
                    />
                ))
            </div>
        </div>
    );
  


ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

【讨论】:

以上是关于列表项没有正确删除(反应)的主要内容,如果未能解决你的问题,请参考以下文章

如何正确删除操作?

无法从 Listview 中删除项目(待办事项列表),长按没有任何反应

删除具有绑定布尔值的列表项 - SwiftUI

列表项旁边的 HTML 按钮无法正确显示

没有正确使用反应生命周期

inf文件 右键安装后 怎么删除或卸载