【问题标题】: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>
            )
          }
        }

【问题讨论】:

    标签: arrays reactjs jsx


    【解决方案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>

    【讨论】:

      猜你喜欢
      • 2020-10-13
      • 2016-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-04
      • 2019-05-05
      • 2022-11-16
      相关资源
      最近更新 更多