1

I want to delete an object from an array by a generated object id.

I've already tried multiple solutions on this and nothing is working.

Handler function:

  handleDeleteTask = id => {
    const task = this.state.tasks.find(i => {
      return i.id === id;
    });

    const newTasks = this.state.tasks.splice(task, 1);
    this.setState({ tasks: newTasks });
  };

JSX:

  {this.state.tasks.map(task => {
          return (
            <Task
              key={task.id}
              task={task.text}
              title={task.title}
              deleteTask={() => this.handleDeleteTask(task.id)}
            />
          );
      })}
1
  • you shouldn't ever call splice on a state object directly! this.state.tasks.splice will mutate the state, instead make a copy const newTasks = [...this.state.tasks] then apply the splice on your newTasks variable Commented Aug 9, 2019 at 17:40

2 Answers 2

4

Edited to reflect the suggestions from comments

splice returns the removed part. You could use filter instead:

  handleDeleteTask = id => {

    const newTasks = [...this.state.tasks].filter(x => x.id !== id);
    this.setState({ tasks: newTasks });
  };

Or spread the original state, splice the copy and set it as new state

  handleDeleteTask = id => {
    const task = this.state.tasks.findIndex(i => {
      return i.id === id;
    })

    const newTasks = [...this.state.tasks]
    newTasks.splice(task, 1)
    this.setState({ tasks: newTasks });
  };

Actually this could be written in one single line

const removeById = id => this.setState({tasks: [...this.state.tasks].filter(x=> x.id !== id)})
Sign up to request clarification or add additional context in comments.

4 Comments

The second part of your answer is incorrect. find returns the element in the array not the index. Splice takes the index
Fixed it. Thank you
yep! probably also can just use findIndex for one iteration rather than 2 scans for the same thing :) Also I'd update each part of your answer to clone the state... even though filter returns a new array its generally a good practice to clone the state object so you dont overlook and accidentally mutate state. anyways +1 from me :)
Updated. Thanks for the suggestions.
2

The first problem is, Array.prototype.splice needs the index of the item you want to delete as the first argument, not the item itself. To find the index instead, change this.state.tasks.find to this.state.tasks.findIndex.

The second problem is splice returns the removed portion of the array, not the new array, so you'd be setting your state to include just the removed item.

Perhaps a simpler approach would be to use Array.prototype.filter to remove the undesired item.

handleDeleteTask = id => {
    this.setState({
        tasks: this.state.tasks.filter(it => it.id !== id)
    })
}

4 Comments

Will still be setting state incorrectly though as well as mutating original
why is that @charlietfl?
Comment was based on only changing to findIndex ... state would then be what was removed not the spliced array
Ah you meant to say state typo threw me off. The other thing is josh needs to update the answer to splice on a clone of state so you dont mutate directly

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.