1 00:00:00,200 --> 00:00:03,503 When we click the plus button to increment a player's score, 2 00:00:03,503 --> 00:00:05,726 we get an error in the console that reads, 3 00:00:05,726 --> 00:00:09,678 Uncaught TypeError: Cannot read property 'setState' of undefined. 4 00:00:09,678 --> 00:00:14,928 The issue here is that we are referencing this.setState inside the increment 5 00:00:14,928 --> 00:00:19,236 score method but this is actually undefined inside the method. 6 00:00:19,236 --> 00:00:26,689 For example, I'll comment out the setState method and log this to the console. 7 00:00:26,689 --> 00:00:32,080 When I click a plus button, notice how this returns undefined. 8 00:00:32,080 --> 00:00:37,910 In objects or classes, this usually refers to the parent that owns the method. 9 00:00:37,910 --> 00:00:40,162 This should be the counter class. 10 00:00:40,162 --> 00:00:44,413 Since this is undefined, our method cannot access this.setState or 11 00:00:44,413 --> 00:00:47,521 this.state when the onClick event is triggered. 12 00:00:47,521 --> 00:00:49,041 So why is it undefined? 13 00:00:49,041 --> 00:00:54,298 You see, when you create a class component that extends from React.Component, 14 00:00:54,298 --> 00:00:58,959 any custom methods you create are not bound to the component by default. 15 00:00:58,959 --> 00:01:01,325 So we've lost our binding to the component, 16 00:01:01,325 --> 00:01:04,819 therefore we're not able to reference it from within our method. 17 00:01:04,819 --> 00:01:09,288 So it's important to remember that you need to bind your custom methods, 18 00:01:09,288 --> 00:01:11,606 so that this refers to the component. 19 00:01:11,606 --> 00:01:15,435 And there are several ways to bind the thisContext in React. 20 00:01:15,435 --> 00:01:18,554 A common way is to call bind in the render method. 21 00:01:18,554 --> 00:01:23,409 Each counter component that gets mounted into the dom is an instance 22 00:01:23,409 --> 00:01:25,035 of the counter class. 23 00:01:25,035 --> 00:01:30,399 So inside the render method, this refers to the counter component instance, 24 00:01:30,399 --> 00:01:32,762 as you can see here in the console. 25 00:01:36,454 --> 00:01:41,557 In the button's onClick event, I'll call the JavaScript 26 00:01:41,557 --> 00:01:48,610 bind method on this.incrementScore, and pass it the desired context via this. 27 00:01:49,940 --> 00:01:54,560 Now let's run our code, click the plus button and great, 28 00:01:54,560 --> 00:01:58,340 we see that the console logged to this now returns the counter. 29 00:01:59,660 --> 00:02:02,665 So now I'll uncomment this.setState, and 30 00:02:02,665 --> 00:02:06,625 remove the console log inside the increment score method. 31 00:02:11,209 --> 00:02:12,862 And we can see that our counter now works. 32 00:02:16,804 --> 00:02:20,837 The other common way to bind event handlers is with an arrow function. 33 00:02:20,837 --> 00:02:22,013 So in my button, 34 00:02:22,013 --> 00:02:27,897 I'll pass an arrow function to the onClick event that calls this.incrementScore 35 00:02:31,988 --> 00:02:35,900 Over in the browser, our counter works the same way. 36 00:02:35,900 --> 00:02:38,870 And we don't even need to bind this, 37 00:02:38,870 --> 00:02:43,420 that's because arrow functions use what's called a lexical this binding which 38 00:02:43,420 --> 00:02:47,860 means that it automatically bind them to the scope in which they are defined. 39 00:02:47,860 --> 00:02:50,096 We know that inside the render method, 40 00:02:50,096 --> 00:02:52,888 this refers to the counter component instance. 41 00:02:52,888 --> 00:02:56,432 The arrow function is enclosed inside the render method, 42 00:02:56,432 --> 00:02:58,466 so it takes on that same context. 43 00:02:58,466 --> 00:03:03,734 And the this value inside it will properly point to the counter component instance. 44 00:03:03,734 --> 00:03:08,474 There are even more ways to bind event handlers, for example, the most 45 00:03:08,474 --> 00:03:13,935 common way to define an event handler in React is with an arrow function. 46 00:03:13,935 --> 00:03:17,298 We learned that arrow functions are automatically bound to the scope in which 47 00:03:17,298 --> 00:03:18,132 they are defined. 48 00:03:18,132 --> 00:03:23,471 So if we rewrite the increment score method as an arrow function, 49 00:03:23,471 --> 00:03:27,753 the function gets bound to the component instance. 50 00:03:27,753 --> 00:03:31,901 The arrow function is enclosed inside the counter class, so 51 00:03:31,901 --> 00:03:34,676 the context is the component instance. 52 00:03:34,676 --> 00:03:37,990 Now we don't need to worry about binding it in the on-click event or 53 00:03:37,990 --> 00:03:41,317 in the constructor which is yet another way to bind custom methods. 54 00:03:41,317 --> 00:03:45,778 We can simply reference and call the function in the onClick event with 55 00:03:45,778 --> 00:03:50,398 this.incrementScore, make sure there are no parentheses at the end. 56 00:03:55,304 --> 00:04:00,188 Good, all right, now that you´ve learned how to create event handlers, 57 00:04:00,188 --> 00:04:03,442 use React events and update state, why don´t you 58 00:04:03,442 --> 00:04:08,271 write a function called decrement score that increases the score by one? 59 00:04:08,271 --> 00:04:10,359 Go ahead and pause the video and give it a try. 60 00:04:12,934 --> 00:04:17,092 So decrement score should work just like increment score, but 61 00:04:17,092 --> 00:04:19,766 subtracting one instead of adding one. 62 00:04:19,766 --> 00:04:25,302 So I'm going to write the event handler as an arrow function by simply 63 00:04:25,302 --> 00:04:31,410 copying the increment score function and changing it to decrement score and 64 00:04:31,410 --> 00:04:37,243 I'll subtract one from the score by changing the plus operator a minus. 65 00:04:37,243 --> 00:04:43,899 Next, I'll add React's onClick event to the minus button, 66 00:04:43,899 --> 00:04:48,123 and pass it, this.decrementScore. 67 00:04:48,123 --> 00:04:53,147 Let's save our code and test that in the browser 68 00:05:01,054 --> 00:05:02,536 All right, our counter feature now works.