列表项没有正确删除(反应) [英] list items are not deleting properly (React)

查看:20
本文介绍了列表项没有正确删除(反应)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果您对我的笔记应用程序有所帮​​助,我将不胜感激.假设我的笔记列表中有 3 个笔记.我想删除列表顶部的注释.无论我尝试删除哪一个,总是先删除列表最底部的那个.我检查了 React 控制台,App 组件状态中的 notes 数组表示它已正确删除.但在实际视图本身,它不是.我怎样才能得到它以便删除我选择的确切笔记?

 class App extends Component {构造函数(道具){超级(道具);this.state = {注:[],标题: "",细节: ""}this.updateTitle = this.updateTitle.bind(this);this.updateDetails = this.updateDetails.bind(this);this.submitHandler = this.submitHandler.bind(this);this.deleteHandler = this.deleteHandler.bind(this);}更新标题(事件){this.setState({ title: event.target.value });}更新细节(事件){this.setState({ 详细信息: event.target.value });}提交处理程序(e){e.preventDefault();如果 (!this.state.title.length || !this.state.details.length) {返回;}const newNote = {新标题:this.state.title,新细节:this.state.details}this.setState(prevState => ({笔记:prevState.notes.concat(newNote),标题: "",细节: ""}))}deleteHandler(id) {this.setState(prevState => ({笔记:prevState.notes.filter((el)=> el !== id)}))}使成为() {返回 (<div className="容器"><h1 className="title">React Notes App</h1><备注表格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) => (<注意条目键={i}标题={note.newTitle}详细信息={note.newDetails}deleteNote={this.deleteHandler.bind(this,note)}/>))}

);}}const NoteForm = (props) =>{返回 (<div><form className="form-section"><输入类名=标题输入"类型=类型"占位符=标题"值={props.titleValue}onChange={props.titleHandle}/><br/><文本区域className="详细信息输入"cols="20"行=3"占位符=详细信息"值={props.detailsValue}onChange={props.detailsHandle}/><br/><按钮类名=输入按钮"onClick={props.onSubmit}>添加注释</button></表单>

)}类 NoteEntry 扩展组件 {构造函数(道具){超级(道具);this.state = {显示:假,假,编辑标题:this.props.title,编辑细节:this.props.details}this.displayToggle = this.displayToggle.bind(this);this.edit = this.edit.bind(this);this.save = this.save.bind(this);}显示切换(){this.setState(prevState => ({显示:!prevState.display}))}编辑() {this.setState({真的})}节省() {让 titleVal = this.refs.updateTitle.value;让 detailsVal = this.refs.updateDetails.value;this.setState({编辑标题:titleVal,编辑详细信息:detailsVal,假})}使成为() {返回 (<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 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}>保存</button>) : (<button className="edit" onClick={this.edit}>Edit</button>)}<button className="delete" onClick={this.props.deleteNote}>删除</button>

)}}

解决方案

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

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

class NoteEntry extends React.Component {构造函数(道具){超级(道具);this.state = {显示:假,假,编辑标题:this.props.title,编辑细节:this.props.details}this.displayToggle = this.displayToggle.bind(this);this.edit = this.edit.bind(this);this.save = this.save.bind(this);}显示切换(){this.setState(prevState => ({显示:!prevState.display}))}编辑() {this.setState({真的})}节省() {让 titleVal = this.refs.updateTitle.value;让 detailsVal = this.refs.updateDetails.value;this.setState({编辑标题:titleVal,编辑详细信息:detailsVal,假})}使成为() {返回 (<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 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}>保存</button>) : (<button className="edit" onClick={this.edit}>Edit</button>)}<button className="delete" onClick={this.props.deleteNote}>删除</button>

)}}const NoteForm = (props) =>{返回 (<div><form className="form-section"><输入类名=标题输入"类型=类型"占位符=标题"值={props.titleValue}onChange={props.titleHandle}/><br/><文本区域className="详细信息输入"cols="20"行=3"占位符=详细信息"值={props.detailsValue}onChange={props.detailsHandle}/><br/><按钮类名=输入按钮"onClick={props.onSubmit}>添加注释</表单>

)}类 App 扩展了 React.Component {构造函数(道具){超级(道具);this.state = {注:[],标题: "",细节: ""}this.updateTitle = this.updateTitle.bind(this);this.updateDetails = this.updateDetails.bind(this);this.submitHandler = this.submitHandler.bind(this);this.deleteHandler = this.deleteHandler.bind(this);}更新标题(事件){this.setState({ title: event.target.value });}更新细节(事件){this.setState({ 详细信息: event.target.value });}提交处理程序(e){e.preventDefault();如果 (!this.state.title.length || !this.state.details.length) {返回;}const newNote = {新标题:this.state.title,新细节:this.state.details}this.setState(prevState => ({笔记:prevState.notes.concat(newNote),标题: "",细节: ""}))}deleteHandler(id) {this.setState(prevState => ({笔记:prevState.notes.filter((el)=> el !== id)}))}使成为() {返回 (<div className="容器"><h1 className="title">React Notes App</h1><备注表格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) => (<注意条目键={note.newTitle}标题={note.newTitle}详细信息={note.newDetails}deleteNote={this.deleteHandler.bind(this,note)}/>))}

);}}ReactDOM.render(, 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>

I'd appreciate some help with my note taking app. Let's say I have 3 notes on my notes list. I want to delete the note at the top of the list. No matter which one I try to delete, it's always whichever note is at the very bottom of the list is deleted first. I checked the React console, and the notes array in the App Component's state says it's deleted properly. But in the actual view itself, it's not. How can I get it so that I delete the exact note that I chose?

    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>
            )
          }
        }

解决方案

This error is occurring from using index as your key. React uses the key attribute to track the elements inside the list. When you are deleting an element from the middle in an array, the index does not delete itself, instead it rearranges and the last index disappears. This is why the last element in your array always got deleted.

For this solution, I have provided title of the note as the key, but this may not be always unique. You will be better using a generated key or a combination of fields as 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>

这篇关于列表项没有正确删除(反应)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆