jakmas
jakmas

Reputation: 93

How to remove item from an array through index in React

I was practicing todo list in React and I faced a problem that I don't understand. Can't delete the item from the array that is in my state. I'm passing the index to my delete function and than I was trying to filter through the array to set a new State.

Here is the code of my App component:

class App extends React.Component {
  state = {
    tasks : []
  }

  addToScreen = (task) => {
    const tasks = { ...this.state.tasks } 
    tasks[`task${Date.now()}`] = task
    this.setState(prevState => ({
      tasks: [...prevState.tasks, task]
    }))
  }


  deleteTask = index => {
    const reducedArr = this.state.tasks.filter( (item) => {
      return item[index] !== item 
    })
    this.setState({
      tasks: reducedArr
    })
  }


  render() {
    return (
      <>
        <Input addToScreen={this.addToScreen}/>
        <Screen tasks={this.state.tasks} deleteTask={this.deleteTask}/>
      </>
    );
  }
}

And here is my Screen component:

class Screen extends React.Component {
  render() {
    return ( 
      <ul>
        {this.props.tasks.map((key, index) => <li key={index}>{key}
        <button onClick={() => this.props.deleteTask(index)}>x</button>
        </li>)}  
      </ul>
    )
  }
}

So it when you press the button on my screen component it should remove the specific value from the state. Thanks for help or any tips!

Upvotes: 1

Views: 15020

Answers (4)

JakePowell
JakePowell

Reputation: 100

I'm also new to React! I've just been working on something similar:

deleteTask = (index) => {

    const reducedArr = [...this.state.tasks];

    reducedArr.splice(index, 1);

    this.setState({tasks: reducedArr})

  }

EDIT: credit here goes to Maximilian Schwarzmüller of Academind. I'm doing the React Complete Guide

Upvotes: 4

arkeros
arkeros

Reputation: 177

You need to bind this to your handler

  render() {
    return (
      <>
        <Screen
          tasks={this.state.tasks}
          deleteTask={this.deleteTask.bind(this)}
        />
      </>
    );
  }

Also, your filter is buggy, is filtering out by value, not by index. I fixed it:

    const reducedArr = this.state.tasks.filter((_, key) => {
      return key !== index;
    });

You have a demo on CodeSandbox

Upvotes: 0

JP de la Torre
JP de la Torre

Reputation: 1751

The right way is to use splice. It removes items from an array and, optionally, replaces them with new ones. This is the syntax:

  array.splice(start[, deleteCount[, item1[, item2[, ...]]]]);

Your function could read:

  deleteTask (index) { // Just so you don't need to bind `this`
    this.state.tasks.splice(index, 1);
    this.setState({
      tasks: this.state.tasks
    })
  }

Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

Upvotes: 0

Mayank Shukla
Mayank Shukla

Reputation: 104369

Instead of item[Index], it should be the index of item in filter callback function.

Like this:

deleteTask = index => {
  const reducedArr = this.state.tasks.filter((item, itemIndex) => {
    return itemIndex !== index 
  })

  this.setState({
    tasks: reducedArr
  })
}

Also use updater function with setState (because you are updating an array and setState is async in nature, check the react doc for more details), write the same function as:

deleteTask = index => {
  this.setState(prevState => ({
    tasks: prevState.tasks.filter((item, itemIndex) => itemIndex != index)
  }))
}

Upvotes: 4

Related Questions