Communicating Between Components5:37 with Guil Hernandez
In this video, we'll refactor the Counter's event handlers, and implement new props in the Player and Counter components that will act as callback functions.
We've restructured our state to be entirely in our main app component. 0:00 But we've lost our functionality of the counter, 0:04 the counter buttons no longer modify the score. 0:06 The buttons in the counter need to alter a piece that state that lives in the app 0:09 component. 0:14 Now, if data flows down in React, how does a child component like 0:14 counter get information back up to its ancestor component? 0:19 Instead of passing state to a child component, 0:23 the parent can pass down a callback function. 0:26 The callback will allow you to communicate events and changes in your data upwards, 0:29 while data continues to flow downwards. 0:34 So next, we'll refactor the counter's event handlers, and implement new 0:36 props in the player and counter components that will act as callback functions. 0:41 In order to design how data flows upward through our component tree, 0:46 we need to think about each component and its responsibilities. 0:49 Counter, for example, has a score passed to it by its parent, 0:53 the player component and player gets to score from its parent, the app component. 0:58 The app component maintains the score state and the buttons intended to 1:06 change the score are two components deep from app in the counter. 1:11 Since data in React flows downward, 1:16 a child component has no way to directly communicate to its parent. 1:19 But React allows us to use props that are callback functions to communicate data 1:23 upstream, from a child to a parent. 1:28 For example, we can write event handlers that manipulate state, and 1:30 pass them down to component as callback functions. 1:34 When a child wants to indicate that the application state should change, 1:37 like click a button to change the score, it will execute the callback function and 1:41 the parent will know what to do to update the data. 1:45 In fact, we've already implemented a simple version of this. 1:48 We wrote the handleRemovePlayer function in the app component which gets 1:51 called down in the player component when the user clicks the delete button. 1:56 The player component has access to the function written in the app class and 2:01 can pass data up to it via the callback function passed as a prop. 2:08 So now we're going to move the counters event handler up to the up component. 2:14 We'll refactor the two functions into one handleScoreChange function that 2:20 changes the score state based on the data passed to it. 2:24 First I'll uncomment the increment score function, cut it out of counter.js and 2:28 paste it inside the app component just above the handle remove player function. 2:33 You can delete the decrementScore function in the counter since we just need one 2:39 function for this. 2:43 Back in app.js I'll change the name of the function to handleScore change. 2:44 And instead of increasing or decreasing the score state by specifying +1 or 2:54 minus 1, the function will accept an argument that specifies the change or 2:59 delta and score. 3:04 I'll pass handleScoreChange, the parameter, delta. 3:06 And I'm choosing the name delta because a delta is the variation of a function, 3:09 in our case the number the score should be changed by. 3:14 You can give this parameter any name you want. 3:17 For now, I'll comment out the setState method, and 3:19 console.log the value of delta. 3:22 Next, we need to pass the handleScoreChange function down to 3:28 the counter component with props. 3:32 We'll first pass it to the player component, 3:34 then supply to the counter component. 3:37 A function will then be called inside the counter using an onClick event. 3:39 So in the map function, 3:43 let's give the player component a new prop named changeScore. 3:45 Then pass the handleScoreChange function with this.handleScoreChange. 3:51 This callback is going to run at a later time through some interaction with a child 3:58 component. 4:03 So in the file, Player.js, 4:04 we will pass the function down to the counter component using props. 4:06 In the return, let's give the counter component a prop named changeScore and 4:10 pass it the function with props.changeScore. 4:18 So now the function is available to be called, or invoked, 4:26 from inside the counter component. 4:30 When a button in the counter is clicked, 4:33 the function will be executed passing in the number the score should be changed by. 4:35 In Counter.js, let's once again provide an onClick event to each button. 4:40 I'll pass onClick an anonymous function that calls props.changeScore. 4:48 Then pass it the delta argument, which is the number to change the score by. 4:56 For the minus button we'll pass -1. 5:00 We can do the same for the + </button>, 5:05 and make it changed by positive 1. 5:10 So now, the handleScoreChange function written in the app 5:14 component knows how to change the score. 5:19 If we run our code, and open up the console, 5:22 clicking a + button, logs a 1, and each- button logs a -1. 5:27
You need to sign up for Treehouse in order to download course files.Sign up