Reputation: 93
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
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
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
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
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