list items are not deleting properly (React)

Solution 1:

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>