Passing a function as a prop

This introduces a very interesting chicken and egg sort of scenario: how do we add a component to a parent from the child component? The list of Todo items lives in TodoList, and our component where we need to add new Todos is a separate component that lives inside of TodoList! There's no internal state for a list of Todos in NewTodo, so how do we make this work?

Easy! We'll create a function in TodoList, which can modify its list of components, and then pass that function into our NewTodo component. So, inside of src/TodoList.js, we'll need to add a new function called addTodo() and we will have to make sure it includes a bind() statement so that no matter where that function lives, it knows how to handle references to this. In the constructor, add our bind statement:

this.addTodo = this.addTodo.bind(this);

Let's move on to writing our addTodo() function. We'll accept a single string, which will be the description that we add. The good news is that this function is super easy to write:

addTodo(item) {
this.setState({ items: [...this.state.items, item] });
}

We're using some new JavaScript syntax here, an array spread. This allows us to essentially take a shortcut with adding new items! Essentially, we want to add new items onto the list of items in the state, but we want to do so in a way that is non-destructive. This will make a modified copy of the item list and preserve the original. We set the list of items equal to this newly-modified array and that's it! All we have to do next is just pass this new addTodo function to NewTodo as a prop:

render() {
return (
<div className="TodoList">
<NewTodo addTodo={this.addTodo} />
{this.renderItems()}
</div>
);
}

Let's hop back over to src/NewTodo.js. We'll need to duplicate our function name, so we'll add an addTodo function inside of NewTodo. This is going to be called via a JavaScript event handler, so we'll need to add a bind statement for it inside of our constructor:

this.addTodo = this.addTodo.bind(this);

And, note the following for our addTodo() function body:

addTodo() {
this.props.addTodo(this.state.item);
this.setState({ item: '' });
}

Remember the addTodo() function that we passed down via props? We'll need to call that function via the props on the object and pass in the item property inside of our state. Remember, item is the value that is getting updated all of the time via our onChange event handlers! Finally, let's modify render() to put it all together:


render() {
return (
<div className="NewTodo">
<input
type="text"
onChange={this.handleUpdate}
value={this.state.item}
/>
&nbsp;&nbsp;
<button onClick={this.addTodo}>Add</button>
</div>
);
}

We need to add a new value property and set it to the current value of the item property from our state. Without doing this, we won't be able to see what is going on when we clear out the state's item property. Finally, we added a new onClick event handler that just calls out to addTodo, just like we prepared for!

Test it out and there we go: interactivity!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.33.87