1

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!

2

4 Answers 4

4

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

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks a lot! I've tried with reducedArr.splice but I messed it up a little.
Be careful, because Array.prototype.splice performs a mutation and According to React Docs: state is a reference to the component state at the time the change is being applied. It should not be directly mutated. Instead, changes should be represented by building a new object based on the input from state and props.
In this case is this not ok as it's mutating reducedArr and then merging the two?
4

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

Comments

0

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

Comments

0

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

Comments

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.