WEBVTT 0 00:00.630 --> 00:07.540 Hey guys. In this lesson I want to tackle this idea of state and introduce you to React 1 00:07.540 --> 00:15.430 hooks as a way of being able to make our website interactive and actually have changeable state. 2 00:15.690 --> 00:17.040 Go ahead and fork 3 00:17.040 --> 00:22.210 the starting project for this lesson. And once you're done 4 00:22.230 --> 00:25.010 have a look at what we've got here now. 5 00:25.050 --> 00:32.120 Unlike our previous React apps, I've actually got all of my React code currently living inside my index 6 00:32.120 --> 00:36.320 .js and there's a reason for this that you're going to discover very soon. 7 00:36.660 --> 00:38.670 But inside our index.js 8 00:38.670 --> 00:40.020 the code is very simple. 9 00:40.110 --> 00:46.650 All that we're doing is rendering a single div that has an

and a button contained inside it. 10 00:46.650 --> 00:55.110 The idea is simple. How can we get this button to trigger an update in this number so that every time 11 00:55.110 --> 01:00.480 the user presses on this plus button, this number actually goes up in value? 12 01:01.740 --> 01:04.650 So let's think about how we might approach this. 13 01:04.650 --> 01:08.430 Well firstly, this

has a hardcoded value in it. 14 01:08.550 --> 01:09.970 So that's not going to work. 15 01:10.020 --> 01:16.920 So let's go ahead and create a new variable called count and let's set it equal to zero and then we'll 16 01:16.920 --> 01:21.480 replace this hardcoded value with this variable count. 17 01:21.480 --> 01:24.200 Nothing has changed so far in the user interface. 18 01:24.210 --> 01:30.540 Now the next thing we need to do is to be able to trigger some piece of code to happen whenever this button 19 01:30.630 --> 01:32.340 is clicked. 20 01:32.340 --> 01:39.930 So we know from our HTML that all of our button elements have a attribute called onClick. And we 21 01:39.930 --> 01:46.920 can set that to equal some sort of function to be triggered when this button receives a click action. 22 01:46.920 --> 01:53.610 Now we know that when we're creating React components that all of these HTML elements and their attributes 23 01:53.910 --> 01:56.390 gets converted into camel case, 24 01:56.490 --> 02:04.270 so something like this. So we can in fact set this onClick attribute to a function in our code. 25 02:04.740 --> 02:10.980 So let me create a function called increase and all that I'm going to put inside is just a simple log 26 02:10.980 --> 02:20.120 statement saying, 'I got clicked.' And now in our onClick I'm going to add a set of curly braces and assign 27 02:20.120 --> 02:22.060 it that function. 28 02:22.070 --> 02:28.820 Now what should happen is when I click this plus button, then it should call this function increase and 29 02:28.820 --> 02:32.420 it should log this message and indeed it does. 30 02:32.450 --> 02:38.290 If you look inside the console I get a new message being logged every time I press this button. 31 02:38.330 --> 02:44.060 So our code is working. But how can we increase the count that's being shown here? 32 02:44.660 --> 02:50.450 Well one way you might think of doing this is to simply just write count++ 33 02:50.600 --> 02:56.270 and this should increase the value of count every time the function increase is called. 34 02:56.270 --> 02:58.100 And indeed it does. 35 02:58.100 --> 03:02.760 Let's go ahead and log the value of count inside the increase function 36 03:02.960 --> 03:07.610 and then I'm going to click on the plus button. And you can see that in the console which is logging 37 03:07.610 --> 03:10.630 the value of count, it is indeed increasing by 1 38 03:10.640 --> 03:16.790 each time I press the button. But our user interface is not changing at all. 39 03:16.790 --> 03:17.780 Nothing is happening. 40 03:17.780 --> 03:19.580 It looks dead to me. 41 03:19.580 --> 03:20.900 So what's going on here? 42 03:21.170 --> 03:27.710 Well remember that even though we're writing HTML elements, they're not actually real elements right? 43 03:27.770 --> 03:35.150 We're relying on the ReactDOM to actually render each of these elements onto the screen. 44 03:35.210 --> 03:41.840 So if we wanted to update what's on screen we actually have to re-render all of this. 45 03:41.840 --> 03:49.070 So if we wanted this to update, one way of doing this instead of console logging would be to call React 46 03:49.100 --> 03:54.870 DOM.render all over again inside our function. 47 03:54.890 --> 04:02.270 Now if I hit save and I click the plus button, you can see that it does indeed work. 48 04:02.480 --> 04:09.260 And every time I press this button effectively what it's doing is re-rendering everything that's on 49 04:09.260 --> 04:13.670 screen which is our div and our

and our button. 50 04:13.670 --> 04:16.080 And this is kind of inefficient 51 04:16.100 --> 04:16.630 right? 52 04:16.640 --> 04:19.280 And besides the code also looks terrible. 53 04:19.280 --> 04:21.120 We have all of this repetition 54 04:21.140 --> 04:23.650 that's not really doing anything for us. 55 04:23.660 --> 04:27.700 So how do people actually solve this problem using React? 56 04:27.710 --> 04:36.890 Well this is where hooks come in. And there's a hook code useState that is perfect for this situation. 57 04:36.890 --> 04:45.400 But one of the rules for using hooks is that you must use a hook inside a functional component. 58 04:45.440 --> 04:51.980 So we have to create a function that renders a component and then inside that function we can use hooks. 59 04:52.010 --> 04:56.030 So let's go ahead and import our App.jsx 60 04:58.790 --> 05:07.360 and move all of our code into our App.js. And then back in our index.js 61 05:07.360 --> 05:11.080 all we need is our ReactDOM.render. 62 05:11.170 --> 05:15.580 And then we're just rendering a simple app component. 63 05:15.580 --> 05:18.050 So now we can focus on our app component. 64 05:18.280 --> 05:25.870 And I'm going to just start off by wrapping everything inside a function which is called App so that 65 05:25.870 --> 05:33.360 this gets rendered and instead of using ReactDOM.render and all of this document get element etc.. 66 05:33.490 --> 05:40.060 All I'm gonna do is just use the return statement so that this becomes the output of our app component 67 05:40.150 --> 05:43.830 and it gets created on screen which you can see right here. 68 05:43.900 --> 05:50.290 Now I'm gonna delete all of this repeated ReactDOM code and you should be left with something that 69 05:50.290 --> 05:51.480 looks like this. 70 05:53.400 --> 06:01.590 Now inside our app component instead of using this count, I'm going to create a new constant that I'm 71 06:01.590 --> 06:06.830 going to call state and I'm going to set the state to React. 72 06:06.870 --> 06:10.770 useState which is a function. 73 06:10.830 --> 06:18.240 Now this useState function comes from the React module so I can either call it like this or as you've 74 06:18.240 --> 06:20.840 seen from the import and export lesson 75 06:20.880 --> 06:29.760 we can also just add a comma and then a set of curly braces and import that use state function as a 76 06:29.820 --> 06:31.760 non default export. 77 06:31.770 --> 06:37.730 So now instead of saying React.useState I can simply just write useState whenever I need it. 78 06:37.800 --> 06:39.360 Now what is this use 79 06:39.360 --> 06:39.910 State 80 06:39.930 --> 06:40.590 exactly 81 06:40.590 --> 06:48.890 anyways? So I'm going to go ahead and comment out my count and also I'm going to delete the count that 82 06:48.890 --> 06:57.140 currently lives inside my

so that I get rid of my errors. And instead I'm just going to log what this 83 06:57.230 --> 07:00.490 state is actually equal to. 84 07:00.510 --> 07:06.200 Notice how state holds the return value of this function useState. 85 07:06.200 --> 07:13.910 And if I log it you can see it's comprised of an array with two items. The first item seems to be undefined 86 07:13.910 --> 07:16.660 and the second item is some sort of function. 87 07:17.000 --> 07:21.040 If I go ahead and add a value in here let's say 0 88 07:21.170 --> 07:23.840 and again my console log gets triggered, 89 07:23.900 --> 07:30.000 you can see the first value of my array gets replaced with whatever it is that I put in here. 90 07:30.290 --> 07:38.600 What's inside these parentheses is basically our starting state and if we wanted to get hold of this 91 07:38.600 --> 07:46.570 value through this state we can simply say state and [0]. 92 07:46.610 --> 07:51.530 So that gets hold of the initial value that we put into this function. 93 07:51.680 --> 07:56.450 And of course now we can then use this state inside our React component. 94 07:56.990 --> 08:02.960 So I'm going to replace that hardcoded 0 once more but this time I'm going to tap into this new array 95 08:02.960 --> 08:09.330 called state and get hold of the first value. And you can see it's now being displayed on screen. 96 08:09.560 --> 08:16.550 And whenever I change my state, you'll see it update automatically in our

. 97 08:17.510 --> 08:23.120 So effectively we're telling this h<1> to track the value of our state. 98 08:23.390 --> 08:31.270 And whenever the state updates then it should also re-render this

. This way 99 08:31.270 --> 08:38.030 it's way more efficient than us calling ReactDOM.render and it only updates the parts that need to 100 08:38.030 --> 08:41.320 be changed, such as this

. 101 08:41.780 --> 08:49.520 Now because the output of useState is an array we're forced to write code like this. If we want to get 102 08:49.520 --> 08:56.630 hold of the first item out of that array, we're using this square bracket notation which is very ugly 103 08:56.630 --> 09:02.740 because it has no meaning. At some point down the line we're going to forget what state zero is and it's 104 09:02.740 --> 09:06.230 gonna be hard to debug other issues when they come up. 105 09:06.440 --> 09:07.910 Now in JavaScript 106 09:07.910 --> 09:08.420 ES6 107 09:08.900 --> 09:17.570 there's this concept called destructuring and what it allows you to do is to destructure a complex structure. 108 09:17.960 --> 09:23.090 So the complex things in JavaScript are objects and arrays. 109 09:23.240 --> 09:28.040 Let's say that I had a constant which was a rgb color 110 09:28.040 --> 09:28.610 right? 111 09:28.670 --> 09:32.160 And it was an array comprised of three values. 112 09:32.960 --> 09:38.420 If we head over to flatuicolors.com which is a really nice color palette where you can simply 113 09:38.420 --> 09:44.300 just copy these color values, let's change the color to the rgb format, 114 09:44.300 --> 09:50.260 so red green blue. And let's just copy this electron blue color. 115 09:50.330 --> 09:58.070 Now if I go ahead and paste this here, you can see that this color is comprised of three elements, the 116 09:58.130 --> 10:01.650 amount of red, the amount of green and the amount of blue. 117 10:01.760 --> 10:10.640 Let me go ahead and add this inside my array. If I wanted to access the amount of red or green or blue, 118 10:11.240 --> 10:20.420 I would have to log something like rgb at index 0 for the amount of red or one for the amounts of 119 10:20.420 --> 10:22.090 green etc.. 120 10:22.100 --> 10:27.020 And this is really bad code because it doesn't mean anything at all. 121 10:27.080 --> 10:34.100 And if this code was separated from where the rgb array was declared and you just saw this out of the 122 10:34.100 --> 10:36.110 blue, I mean what does that even mean 123 10:36.110 --> 10:36.860 right? 124 10:37.070 --> 10:38.540 What can we do instead? 125 10:38.540 --> 10:47.780 Well we can destructure this array so that instead of having this name rgb, we can use a set of square 126 10:47.780 --> 10:48.450 brackets. 127 10:48.470 --> 10:54.280 Remember that we're working with an array and arrays are declared using square brackets 128 10:54.320 --> 11:01.250 so we also deconstruct them using a square bracket. And then we can provide some names for each of the 129 11:01.250 --> 11:05.570 elements inside the array ordered by their positions. 130 11:05.570 --> 11:09.980 So I could call the item at index 1 red, the next one 131 11:09.980 --> 11:12.670 green and the last one blue. 132 11:13.250 --> 11:15.070 And what's going to happen behind the scenes 133 11:15.110 --> 11:21.130 is this variable name red is going to be mapped to this first value, 134 11:21.140 --> 11:23.750 green is going to remap to the second value 135 11:23.750 --> 11:26.630 and blue is going to be mapped to the third value. 136 11:26.630 --> 11:34.510 So now if I simply just log the value of blue, you can see that third value gets outputed. 137 11:34.640 --> 11:43.420 So given that we know that this useState function outputs an array with a value and a function, 138 11:44.020 --> 11:48.670 then we can give each of these a name instead of just calling it state. 139 11:49.090 --> 11:52.240 So let's open up a set of square brackets 140 11:52.240 --> 11:57.640 and given that we're going to be using this state to hold the value of our counter, I'm going to give 141 11:57.640 --> 12:02.440 the first item of the array a name which is called count. 142 12:02.440 --> 12:10.570 So now whenever I want to access the value that's stored inside the state, all I have to do instead of 143 12:10.570 --> 12:17.360 saying state at position 0 I can simply just happen to count and it does the same thing. 144 12:17.500 --> 12:24.490 It gets hold of the output of this function, which is an array with two items and because we've only 145 12:24.490 --> 12:31.420 got one name specified in our destructuring, it assigns this name to the first value which is the initial 146 12:31.420 --> 12:33.010 value. 147 12:33.010 --> 12:37.750 So how do we use this useState hook to update its value? 148 12:37.750 --> 12:44.200 Because yeah it's great that we can change the initial value but how can we change it later on? 149 12:44.200 --> 12:50.650 For example when we want to call increase. What's the equivalent of the count++? 150 12:50.680 --> 12:57.900 Well remember that we mentioned that this array that gets returned from this function has two items. 151 12:57.970 --> 12:59.510 The first one is a value 152 12:59.530 --> 13:06.760 and the second one is a function. Well we can give that function a name. Let's call it setCount because 153 13:06.760 --> 13:08.860 that's basically what it's going to do. 154 13:08.860 --> 13:16.420 This is gonna be the function that's going to be used to update this value inside our state. Inside the 155 13:16.600 --> 13:17.960 increase function 156 13:17.980 --> 13:22.300 I'm going to call setCount and I'm gonna pass it a new value. 157 13:22.300 --> 13:24.700 So let's say maybe 12. 158 13:25.000 --> 13:32.050 So now let's track what's going to happen. First when my app loads up I call you state and I give it 159 13:32.110 --> 13:33.630 an initial value. 160 13:33.850 --> 13:40.900 This value gets stored inside this variable count and it gets rendered inside our

. 161 13:40.900 --> 13:48.280 Now when the user presses on this button and the onClick gets triggered, the increase function is activated. 162 13:48.580 --> 13:55.870 And this increase function is going to call set count which is going to update the state of my count 163 13:55.960 --> 13:59.050 variable and I'm setting it to equal 12. 164 13:59.710 --> 14:04.530 Let's go ahead and take a look in our website. When we refresh 165 14:04.540 --> 14:08.890 it starts out with this initial value for the count. 166 14:09.130 --> 14:15.850 And then when I press the plus button, it gets set to whatever it is that I set it to inside the increase 167 14:15.850 --> 14:16.870 function. 168 14:16.930 --> 14:22.240 But notice how if I keep pressing this nothing happens. It's just going to keep resetting it to 12 which 169 14:22.240 --> 14:24.970 is not very useful for a counter app. 170 14:24.970 --> 14:26.170 What can we do instead? 171 14:26.560 --> 14:30.920 Well let's set this count to 0 to begin with, 172 14:31.000 --> 14:39.070 make it more like a counter. And then I'm going to set my count to the current value of count + 1. 173 14:39.100 --> 14:41.710 So count + 1. 174 14:41.710 --> 14:50.490 And now when I press this button we'll see that it just increases by 1 each time. As a challenge 175 14:50.530 --> 14:58.840 go ahead and create another button down here and instead of increasing the value, you want it to decrease 176 14:58.840 --> 14:59.950 the value. 177 15:00.100 --> 15:02.960 So it should have a minus sign inside 178 15:03.190 --> 15:06.870 and when you click on it, it should go the opposite way. 179 15:06.880 --> 15:10.330 Pause the video now and see if you can complete this challenge 180 15:15.810 --> 15:20.220 All right. So we've got an increase function that's tied to the plus button. 181 15:20.220 --> 15:28.090 But we should probably also have a decrease function that's tied to the minus button. 182 15:28.350 --> 15:34.830 Now when this button gets clicked we trigger the decrease function and inside here we are again going 183 15:34.830 --> 15:40.880 to call setCount which is the function that's going to allow us to update the value of count. 184 15:41.070 --> 15:44.760 And we're going to say count - 1. 185 15:44.760 --> 15:50.300 So now if we update our website and we press the plus it goes up, we press the minus 186 15:50.310 --> 16:00.360 it goes down. And this is all achieved using the useState hook. To recap, in this lesson we're introducing 187 16:00.360 --> 16:05.010 this concept of state in order to have interactivity in our app. 188 16:05.160 --> 16:11.280 And what we're trying to achieve is for our website to be able to update dynamically reflecting the 189 16:11.280 --> 16:12.930 updated state. 190 16:12.930 --> 16:19.910 Now the state comes from this useState hook and this function comes from the React module. 191 16:19.920 --> 16:27.630 Now when we first call this function, we get to define an initial value. And then we get to use this value 192 16:27.990 --> 16:31.980 inside our destructed array which we called count. 193 16:31.980 --> 16:39.750 So we're putting that value of count inside our

and then we get to trigger the set count which 194 16:39.750 --> 16:43.570 is the function that's going to update the value of count. 195 16:43.710 --> 16:50.220 And we do that when the user clicks on our plus button. And we set it to the current value of count + 196 16:50.340 --> 16:51.090 1, 197 16:51.090 --> 16:55.500 so it increases it by 1 each time. 198 16:55.500 --> 17:01.620 Now the idea of hooks might be quite unfamiliar to you but once you wrap your head around its mechanism 199 17:02.070 --> 17:08.800 it's incredibly powerful and really useful when you want to create any sort of interactive app. 200 17:08.820 --> 17:13.320 Now don't worry if you're still trying to get to grips with this concept because it's something that 201 17:13.320 --> 17:20.190 is quite foreign and I recommend as a first step to simply delete all of the code that you have in your 202 17:20.220 --> 17:27.600 code sandbox right now and then to recreate this app from scratch yourself. So delete everything that's 203 17:27.600 --> 17:35.190 inside App.js and refresh yourself just simply on the syntax to begin with because it looks pretty 204 17:35.190 --> 17:42.060 weird. And in the next lesson I've got a another challenge for you to implement this use 205 17:42.100 --> 17:42.940 State hook. 206 17:42.990 --> 17:45.420 So you're going to be getting plenty of practice 207 17:45.600 --> 17:50.320 and we're also going to be talking about destructuring a little bit later on as well. 208 17:50.430 --> 17:55.950 For now what I want you to do is just to get familiar with the syntax. Be able to write this code from 209 17:55.950 --> 18:01.710 scratch yourself without looking at the video and be able to understand how we actually got here in 210 18:01.710 --> 18:02.940 the first place. 211 18:03.030 --> 18:08.570 So pause the video now, have a play around with the sandbox and I'll see you on the next lesson for a challenge.