Reputation: 2724
I'm trying to pass down a function called handleDeleteToDoItem
from the parent ToDoContainer
to the child ToDoListOfItems
.
This is done with <ToDoListOfItems toDoItems={this.state.toDoItems} deleteToDoItem={this.handleDeleteToDoItem} />
However, I'm getting an error that the function is never received by the child class when I reference it with this.props.deleteToDoItem
when I'm rendering ToDoItems
inside of ToDoListOfItems
All of the other states which I've passed down from ToDoContainer
are being recognized, except for deleteToDoItem
and I'm at a loss of what I've done wrong here. My IDE (Webstorm) is telling me the variable is unresolved.
Is there a different way I should be passing down functions from parent components to child components?
Thanks,
import React, {Component} from 'react';
import './App.css';
class ToDoContainer extends Component {
constructor(props) {
super(props);
this.state = {
toDoItems: [],
toDoWhat: ""
};
...
this.handleDeleteToDoItem = this.handleDeleteToDoItem.bind(this);
}
handleDeleteToDoItem(uniqueID) {
let updatedItemList = this.state.toDoItems.filter(toDo => {
return toDo.uniqueID !== uniqueID;
});
// Concat updated item list to blank array
this.setState({
toDoItems: [].concat(updatedItemList)
})
}
render() {
return (
<div>
<div>
<div>
<ToDoListOfItems toDoItems={this.state.toDoItems} deleteToDoItem={this.handleDeleteToDoItem} />
</div>
</div>
{/* TODO Create a form with a submit button to add items to the todolist */}
<form action="">
<div>
{/* Capture the value of the form input */}
<input type="text" onChange={this.handleChangeToDoItem} value={this.state.toDoWhat}/>
</div>
<div>
<button onClick={this.handleAddToDoItem}>Add Item to List</button>
</div>
</form>
</div>
);
}
}
// This is the container for all the indivdual items in the to-do list
class ToDoListOfItems extends Component {
render() {
//TODO Put in styling for the list of items
// Use map() to iterate through each item in the to-do list, creating new elements in the list container
return (
<ul>
{this.props.toDoItems.map(toDo => (
<ToDoItem key={toDo.uniqueID}
id={toDo.uniqueID}
toDoWhat={toDo.toDoWhat}
completed={toDo.isDone}
onDelete={this.props.deleteToDoItem}/>
))}
</ul>
)
}
}
Upvotes: 2
Views: 205
Reputation: 771
Try making the deleteToDoItem
prop in the container class equal to an arrow function calling the handleDeleteToDoItem
with parameters:
... deleteToDoItem={uniqueID => this.handleDeleteToDoItem(uniqueID)}
Also, using an arrow function in this way makes it so you don't need to explicitly bind the handler function. Make it into an arrow function (above) and it is automatically bound.
Upvotes: 0
Reputation: 104379
Its a key name mismatch issue, because in ToDoItem
you are passing the function by key onDelete
not by deleteToDoItem
:
Here:
<ToDoItem key={toDo.uniqueID}
id={toDo.uniqueID}
toDoWhat={toDo.toDoWhat}
completed={toDo.isDone}
onDelete={this.props.deleteToDoItem} // here
/>
So inside ToDoItem
component it will be available by this.props.onDelete
.
Suggestion: To avoid the confusion use key deleteToDoItem
at all the places.
Upvotes: 1