Reputation: 63
I am trying to create a todo list using React but i cant seem to understand why I am getting the error: "Warning: Cannot update during an existing state transition (such as within render
). Render methods should be a pure function of props and state."
Here's the code:
import React from 'react'
import ReactDOM from 'react-dom'
class Todo extends React.Component{
constructor(props){
super(props)
this.state = {
input: '',
list: []
}
this.handleChange = this.handleChange.bind(this)
this.reset = this.reset.bind(this)
this.removeItem = this.removeItem.bind(this)
this.add = this.add.bind(this)
}
add(){ //Adds a new task
const newItem = {
value: this.state.input,
id: Math.random + Math.random
};
const listed = [...this.state.list]
listed.push(newItem)
this.setState({
input: '',
list: listed
})
}
removeItem(id){ //deletes a task
const list = [...this.state.list]
const updatedList = list.filter(obj => {
return obj.id !== id
})
this.setState({
list: updatedList
})
}
handleChange(e){
this.setState({input: e.target.value})
}
reset(e){
e.preventDefault()
}
render(){
return (
<div>
<form action="" onSubmit={this.reset}>
<input type="text" value={this.state.input} placeholder='Enter a task..' onChange={this.handleChange} />
<button onClick={this.add}>Add Task</button>
{this.state.list.map(item => { //updates when a task is added or removed
return (
<div key={item.id}>
<h1>{item.value}</h1>
<button onClick={this.removeItem(item.id)}>X</button>
</div>
)
})}
</form>
</div>
)
}
}
ReactDOM.render(<Todo />,document.getElementById('root'))
Upvotes: 0
Views: 142
Reputation: 1
<button onClick={this.removeItem(item.id)}>X</button>
In this button the event handler you have provided runs immediately due to the presents of the ()
at the end. To prevent this and still provide your argument item.id
you can enclose the handler this.removeItem(item.id)
with in another function.
I like the arrow function for this so mine looks like this
<button onClick={ ()=>this.removeItem(item.id) }>X</button>
.
Math.random + Math.random
is not returning a number like you would want for the element key. This is because your have neglected to include ()
at telling JS to run the function and return an int.
After making these changes, I ran it in codepen.io and it seemed to work fine.
Upvotes: 0
Reputation: 8774
Because you are calling removeItem on render. It needs to be wrapped in a separate function:
<button onClick={() => this.removeItem(item.id)}>X</button>
So that you only call it onClick and not on render.
Upvotes: 2