Reputation: 23
I"ve been trying my hands on learning react and just hit a snag. Having issue understanding passing props across child components as relates to the problem being encountered. I'm having problems deleting an item from my todo list and can for the life of me figure out wat's wrong.
import React, { Component } from 'react';
import Form from './components/Form';
import Todo from './components/Todo';
class App extends Component {
constructor(props){
super(props);
this.state = {
userInput: "",
todoList: []
}
this.onChange= this.onChange.bind(this);
this.addItem=this.addItem.bind(this);
this.handleDelete=this.handleDelete(this);
}
//update input state
onChange=(e)=>{
this.setState({
userInput: e.target.value
})
}
//update todo list
addItem=(e)=>{
e.preventDefault();
if(this.state.userInput!==""){
const userData={
//create a specific user id for each input
id: Math.random(),
value: this.state.userInput
}
const list=[...this.state.todoList];
list.push(userData);
//Reset userInput after inputing data
this.setState({
userInput: "",
todoList: list
})
}
}
//Deleting an item
handleDelete=(id)=>{
const list=[...this.state.todoList];
const updatedList=list.filter(item=>item.id!==id)
this.setState({
todoList:updatedList
})
}
render() {
return(
<div>
<h1>
My Todo List
</h1>
<Form value={this.state.userInput} onChange={this.onChange} onSubmit={this.addItem} />
<Todo list={this.state.todoList} onDelete={this.handleDelete}/>
</div>
)
}
}
export default App;
Above is the parent component
import React, { Component } from 'react';
class Form extends Component {
render() {
return (
<div>
<form >
<input type="text" value={this.props.value} onChange={this.props.onChange}/><button className="btn btn-primary" type="submit" onClick={this.props.onSubmit}>add</button>
</form>
</div>
);
}
}
export default Form;
import React, { Component } from 'react';
class Todo extends Component {
render() {
const todos=this.props.list.map((item,index)=><li key={item.id}>{item.value} <i onClick={this.props.onDelete(item.id)} class="fas fa-trash"></i></li>)
return (
<div>
<ul>
{todos}
</ul>
</div>
);
}
}
export default Todo;
Upvotes: 1
Views: 1202
Reputation: 59541
You almost got it right. You need to provide a callback to your onClick handler.
The way you have it now you are providing the onClick handler with the result of running that function. In other words onDelete
is being called on each render and onClick
is given the return value of onDelete
(which is undefined).
You want to give it the function itself. Just change it to:
onClick={() => this.props.onDelete(item.id)}
EDIT: You also made a mistake in your binding of this.handleDelete
. It should be:
this.handleDelete = this.handleDelete.bind(this);
but you did:
this.handleDelete = this.handleDelete(this);
which is why you got the error.
Upvotes: 1
Reputation: 6777
Apparently, your Todo
component isn't providing the click handler properly:
<i onClick={this.props.onDelete(item.id)} class="fas fa-trash"></i>
should be:
<i onClick={() => this.props.onDelete(item.id)} class="fas fa-trash"></i>
The reason is because onClick
expects a function and passing it this way onClick={this.props.onDelete(item.id)}
provides the return of the onDelete
function.
Upvotes: 1