0 1 00:00:00,630 --> 00:00:07,540 Hey guys. In this lesson I want to tackle this idea of state and introduce you to React 1 2 00:00:07,540 --> 00:00:15,430 hooks as a way of being able to make our website interactive and actually have changeable state. 2 3 00:00:15,690 --> 00:00:17,040 Go ahead and fork 3 4 00:00:17,040 --> 00:00:22,210 the starting project for this lesson. And once you're done 4 5 00:00:22,230 --> 00:00:25,010 have a look at what we've got here now. 5 6 00:00:25,050 --> 00:00:32,120 Unlike our previous React apps, I've actually got all of my React code currently living inside my index 6 7 00:00:32,120 --> 00:00:36,320 .js and there's a reason for this that you're going to discover very soon. 7 8 00:00:36,660 --> 00:00:38,670 But inside our index.js 8 9 00:00:38,670 --> 00:00:40,020 the code is very simple. 9 10 00:00:40,110 --> 00:00:46,650 All that we're doing is rendering a single div that has an

and a button contained inside it. 10 11 00:00:46,650 --> 00: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 12 00:00:55,110 --> 00:01:00,480 the user presses on this plus button, this number actually goes up in value? 12 13 00:01:01,740 --> 00:01:04,650 So let's think about how we might approach this. 13 14 00:01:04,650 --> 00:01:08,430 Well firstly, this

has a hardcoded value in it. 14 15 00:01:08,550 --> 00:01:09,970 So that's not going to work. 15 16 00:01:10,020 --> 00: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 17 00:01:16,920 --> 00:01:21,480 replace this hardcoded value with this variable count. 17 18 00:01:21,480 --> 00:01:24,200 Nothing has changed so far in the user interface. 18 19 00:01:24,210 --> 00: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 20 00:01:30,630 --> 00:01:32,340 is clicked. 20 21 00:01:32,340 --> 00:01:39,930 So we know from our HTML that all of our button elements have a attribute called onClick. And we 21 22 00:01:39,930 --> 00:01:46,920 can set that to equal some sort of function to be triggered when this button receives a click action. 22 23 00:01:46,920 --> 00:01:53,610 Now we know that when we're creating React components that all of these HTML elements and their attributes 23 24 00:01:53,910 --> 00:01:56,390 gets converted into camel case, 24 25 00:01:56,490 --> 00:02:04,270 so something like this. So we can in fact set this onClick attribute to a function in our code. 25 26 00:02:04,740 --> 00: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 27 00:02:10,980 --> 00: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 28 00:02:20,120 --> 00:02:22,060 it that function. 28 29 00:02:22,070 --> 00:02:28,820 Now what should happen is when I click this plus button, then it should call this function increase and 29 30 00:02:28,820 --> 00:02:32,420 it should log this message and indeed it does. 30 31 00:02:32,450 --> 00:02:38,290 If you look inside the console I get a new message being logged every time I press this button. 31 32 00:02:38,330 --> 00:02:44,060 So our code is working. But how can we increase the count that's being shown here? 32 33 00:02:44,660 --> 00:02:50,450 Well one way you might think of doing this is to simply just write count++ 33 34 00:02:50,600 --> 00:02:56,270 and this should increase the value of count every time the function increase is called. 34 35 00:02:56,270 --> 00:02:58,100 And indeed it does. 35 36 00:02:58,100 --> 00:03:02,760 Let's go ahead and log the value of count inside the increase function 36 37 00:03:02,960 --> 00: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 38 00:03:07,610 --> 00:03:10,630 the value of count, it is indeed increasing by 1 38 39 00:03:10,640 --> 00:03:16,790 each time I press the button. But our user interface is not changing at all. 39 40 00:03:16,790 --> 00:03:17,780 Nothing is happening. 40 41 00:03:17,780 --> 00:03:19,580 It looks dead to me. 41 42 00:03:19,580 --> 00:03:20,900 So what's going on here? 42 43 00:03:21,170 --> 00:03:27,710 Well remember that even though we're writing HTML elements, they're not actually real elements right? 43 44 00:03:27,770 --> 00:03:35,150 We're relying on the ReactDOM to actually render each of these elements onto the screen. 44 45 00:03:35,210 --> 00:03:41,840 So if we wanted to update what's on screen we actually have to re-render all of this. 45 46 00:03:41,840 --> 00: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 47 00:03:49,100 --> 00:03:54,870 DOM.render all over again inside our function. 47 48 00:03:54,890 --> 00:04:02,270 Now if I hit save and I click the plus button, you can see that it does indeed work. 48 49 00:04:02,480 --> 00:04:09,260 And every time I press this button effectively what it's doing is re-rendering everything that's on 49 50 00:04:09,260 --> 00:04:13,670 screen which is our div and our

and our button. 50 51 00:04:13,670 --> 00:04:16,080 And this is kind of inefficient 51 52 00:04:16,100 --> 00:04:16,630 right? 52 53 00:04:16,640 --> 00:04:19,280 And besides the code also looks terrible. 53 54 00:04:19,280 --> 00:04:21,120 We have all of this repetition 54 55 00:04:21,140 --> 00:04:23,650 that's not really doing anything for us. 55 56 00:04:23,660 --> 00:04:27,700 So how do people actually solve this problem using React? 56 57 00:04:27,710 --> 00:04:36,890 Well this is where hooks come in. And there's a hook code useState that is perfect for this situation. 57 58 00:04:36,890 --> 00:04:45,400 But one of the rules for using hooks is that you must use a hook inside a functional component. 58 59 00:04:45,440 --> 00:04:51,980 So we have to create a function that renders a component and then inside that function we can use hooks. 59 60 00:04:52,010 --> 00:04:56,030 So let's go ahead and import our App.jsx 60 61 00:04:58,790 --> 00:05:07,360 and move all of our code into our App.js. And then back in our index.js 61 62 00:05:07,360 --> 00:05:11,080 all we need is our ReactDOM.render. 62 63 00:05:11,170 --> 00:05:15,580 And then we're just rendering a simple app component. 63 64 00:05:15,580 --> 00:05:18,050 So now we can focus on our app component. 64 65 00:05:18,280 --> 00:05:25,870 And I'm going to just start off by wrapping everything inside a function which is called App so that 65 66 00:05:25,870 --> 00:05:33,360 this gets rendered and instead of using ReactDOM.render and all of this document get element etc.. 66 67 00:05:33,490 --> 00: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 68 00:05:40,150 --> 00:05:43,830 and it gets created on screen which you can see right here. 68 69 00:05:43,900 --> 00:05:50,290 Now I'm gonna delete all of this repeated ReactDOM code and you should be left with something that 69 70 00:05:50,290 --> 00:05:51,480 looks like this. 70 71 00:05:53,400 --> 00: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 72 00:06:01,590 --> 00:06:06,830 going to call state and I'm going to set the state to React. 72 73 00:06:06,870 --> 00:06:10,770 useState which is a function. 73 74 00:06:10,830 --> 00: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 75 00:06:18,240 --> 00:06:20,840 seen from the import and export lesson 75 76 00:06:20,880 --> 00: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 77 00:06:29,820 --> 00:06:31,760 non default export. 77 78 00:06:31,770 --> 00:06:37,730 So now instead of saying React.useState I can simply just write useState whenever I need it. 78 79 00:06:37,800 --> 00:06:39,360 Now what is this use 79 80 00:06:39,360 --> 00:06:39,910 State 80 81 00:06:39,930 --> 00:06:40,590 exactly 81 82 00:06:40,590 --> 00: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 83 00:06:48,890 --> 00: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 84 00:06:57,230 --> 00:07:00,490 state is actually equal to. 84 85 00:07:00,510 --> 00:07:06,200 Notice how state holds the return value of this function useState. 85 86 00:07:06,200 --> 00: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 87 00:07:13,910 --> 00:07:16,660 and the second item is some sort of function. 87 88 00:07:17,000 --> 00:07:21,040 If I go ahead and add a value in here let's say 0 88 89 00:07:21,170 --> 00:07:23,840 and again my console log gets triggered, 89 90 00:07:23,900 --> 00:07:30,000 you can see the first value of my array gets replaced with whatever it is that I put in here. 90 91 00:07:30,290 --> 00:07:38,600 What's inside these parentheses is basically our starting state and if we wanted to get hold of this 91 92 00:07:38,600 --> 00:07:46,570 value through this state we can simply say state and [0]. 92 93 00:07:46,610 --> 00:07:51,530 So that gets hold of the initial value that we put into this function. 93 94 00:07:51,680 --> 00:07:56,450 And of course now we can then use this state inside our React component. 94 95 00:07:56,990 --> 00: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 96 00:08:02,960 --> 00:08:09,330 called state and get hold of the first value. And you can see it's now being displayed on screen. 96 97 00:08:09,560 --> 00:08:16,550 And whenever I change my state, you'll see it update automatically in our

. 97 98 00:08:17,510 --> 00:08:23,120 So effectively we're telling this h<1> to track the value of our state. 98 99 00:08:23,390 --> 00:08:31,270 And whenever the state updates then it should also re-render this

. This way 99 100 00:08:31,270 --> 00:08:38,030 it's way more efficient than us calling ReactDOM.render and it only updates the parts that need to 100 101 00:08:38,030 --> 00:08:41,320 be changed, such as this

. 101 102 00:08:41,780 --> 00: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 103 00:08:49,520 --> 00:08:56,630 hold of the first item out of that array, we're using this square bracket notation which is very ugly 103 104 00:08:56,630 --> 00: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 105 00:09:02,740 --> 00:09:06,230 gonna be hard to debug other issues when they come up. 105 106 00:09:06,440 --> 00:09:07,910 Now in JavaScript 106 107 00:09:07,910 --> 00:09:08,420 ES6 107 108 00:09:08,900 --> 00:09:17,570 there's this concept called destructuring and what it allows you to do is to destructure a complex structure. 108 109 00:09:17,960 --> 00:09:23,090 So the complex things in JavaScript are objects and arrays. 109 110 00:09:23,240 --> 00:09:28,040 Let's say that I had a constant which was a rgb color 110 111 00:09:28,040 --> 00:09:28,610 right? 111 112 00:09:28,670 --> 00:09:32,160 And it was an array comprised of three values. 112 113 00:09:32,960 --> 00:09:38,420 If we head over to flatuicolors.com which is a really nice color palette where you can simply 113 114 00:09:38,420 --> 00:09:44,300 just copy these color values, let's change the color to the rgb format, 114 115 00:09:44,300 --> 00:09:50,260 so red green blue. And let's just copy this electron blue color. 115 116 00:09:50,330 --> 00: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 117 00:09:58,130 --> 00:10:01,650 amount of red, the amount of green and the amount of blue. 117 118 00:10:01,760 --> 00: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 119 00:10:11,240 --> 00: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 120 00:10:20,420 --> 00:10:22,090 green etc.. 120 121 00:10:22,100 --> 00:10:27,020 And this is really bad code because it doesn't mean anything at all. 121 122 00:10:27,080 --> 00: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 123 00:10:34,100 --> 00:10:36,110 blue, I mean what does that even mean 123 124 00:10:36,110 --> 00:10:36,860 right? 124 125 00:10:37,070 --> 00:10:38,540 What can we do instead? 125 126 00:10:38,540 --> 00: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 127 00:10:47,780 --> 00:10:48,450 brackets. 127 128 00:10:48,470 --> 00:10:54,280 Remember that we're working with an array and arrays are declared using square brackets 128 129 00:10:54,320 --> 00:11:01,250 so we also deconstruct them using a square bracket. And then we can provide some names for each of the 129 130 00:11:01,250 --> 00:11:05,570 elements inside the array ordered by their positions. 130 131 00:11:05,570 --> 00:11:09,980 So I could call the item at index 1 red, the next one 131 132 00:11:09,980 --> 00:11:12,670 green and the last one blue. 132 133 00:11:13,250 --> 00:11:15,070 And what's going to happen behind the scenes 133 134 00:11:15,110 --> 00:11:21,130 is this variable name red is going to be mapped to this first value, 134 135 00:11:21,140 --> 00:11:23,750 green is going to remap to the second value 135 136 00:11:23,750 --> 00:11:26,630 and blue is going to be mapped to the third value. 136 137 00:11:26,630 --> 00:11:34,510 So now if I simply just log the value of blue, you can see that third value gets outputed. 137 138 00:11:34,640 --> 00:11:43,420 So given that we know that this useState function outputs an array with a value and a function, 138 139 00:11:44,020 --> 00:11:48,670 then we can give each of these a name instead of just calling it state. 139 140 00:11:49,090 --> 00:11:52,240 So let's open up a set of square brackets 140 141 00:11:52,240 --> 00: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 142 00:11:57,640 --> 00:12:02,440 the first item of the array a name which is called count. 142 143 00:12:02,440 --> 00: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 144 00:12:10,570 --> 00:12:17,360 saying state at position 0 I can simply just happen to count and it does the same thing. 144 145 00:12:17,500 --> 00: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 146 00:12:24,490 --> 00:12:31,420 got one name specified in our destructuring, it assigns this name to the first value which is the initial 146 147 00:12:31,420 --> 00:12:33,010 value. 147 148 00:12:33,010 --> 00:12:37,750 So how do we use this useState hook to update its value? 148 149 00:12:37,750 --> 00:12:44,200 Because yeah it's great that we can change the initial value but how can we change it later on? 149 150 00:12:44,200 --> 00:12:50,650 For example when we want to call increase. What's the equivalent of the count++? 150 151 00:12:50,680 --> 00:12:57,900 Well remember that we mentioned that this array that gets returned from this function has two items. 151 152 00:12:57,970 --> 00:12:59,510 The first one is a value 152 153 00:12:59,530 --> 00: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 154 00:13:06,760 --> 00:13:08,860 that's basically what it's going to do. 154 155 00:13:08,860 --> 00: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 156 00:13:16,600 --> 00:13:17,960 increase function 156 157 00:13:17,980 --> 00:13:22,300 I'm going to call setCount and I'm gonna pass it a new value. 157 158 00:13:22,300 --> 00:13:24,700 So let's say maybe 12. 158 159 00:13:25,000 --> 00: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 160 00:13:32,110 --> 00:13:33,630 an initial value. 160 161 00:13:33,850 --> 00:13:40,900 This value gets stored inside this variable count and it gets rendered inside our

. 161 162 00:13:40,900 --> 00:13:48,280 Now when the user presses on this button and the onClick gets triggered, the increase function is activated. 162 163 00:13:48,580 --> 00:13:55,870 And this increase function is going to call set count which is going to update the state of my count 163 164 00:13:55,960 --> 00:13:59,050 variable and I'm setting it to equal 12. 164 165 00:13:59,710 --> 00:14:04,530 Let's go ahead and take a look in our website. When we refresh 165 166 00:14:04,540 --> 00:14:08,890 it starts out with this initial value for the count. 166 167 00:14:09,130 --> 00: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 168 00:14:15,850 --> 00:14:16,870 function. 168 169 00:14:16,930 --> 00: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 170 00:14:22,240 --> 00:14:24,970 is not very useful for a counter app. 170 171 00:14:24,970 --> 00:14:26,170 What can we do instead? 171 172 00:14:26,560 --> 00:14:30,920 Well let's set this count to 0 to begin with, 172 173 00:14:31,000 --> 00: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 174 00:14:39,100 --> 00:14:41,710 So count + 1. 174 175 00:14:41,710 --> 00: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 176 00:14:50,530 --> 00:14:58,840 go ahead and create another button down here and instead of increasing the value, you want it to decrease 176 177 00:14:58,840 --> 00:14:59,950 the value. 177 178 00:15:00,100 --> 00:15:02,960 So it should have a minus sign inside 178 179 00:15:03,190 --> 00:15:06,870 and when you click on it, it should go the opposite way. 179 180 00:15:06,880 --> 00:15:10,330 Pause the video now and see if you can complete this challenge 180 181 00:15:15,810 --> 00:15:20,220 All right. So we've got an increase function that's tied to the plus button. 181 182 00:15:20,220 --> 00:15:28,090 But we should probably also have a decrease function that's tied to the minus button. 182 183 00:15:28,350 --> 00:15:34,830 Now when this button gets clicked we trigger the decrease function and inside here we are again going 183 184 00:15:34,830 --> 00:15:40,880 to call setCount which is the function that's going to allow us to update the value of count. 184 185 00:15:41,070 --> 00:15:44,760 And we're going to say count - 1. 185 186 00:15:44,760 --> 00:15:50,300 So now if we update our website and we press the plus it goes up, we press the minus 186 187 00:15:50,310 --> 00:16:00,360 it goes down. And this is all achieved using the useState hook. To recap, in this lesson we're introducing 187 188 00:16:00,360 --> 00:16:05,010 this concept of state in order to have interactivity in our app. 188 189 00:16:05,160 --> 00:16:11,280 And what we're trying to achieve is for our website to be able to update dynamically reflecting the 189 190 00:16:11,280 --> 00:16:12,930 updated state. 190 191 00:16:12,930 --> 00:16:19,910 Now the state comes from this useState hook and this function comes from the React module. 191 192 00:16:19,920 --> 00: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 193 00:16:27,990 --> 00:16:31,980 inside our destructed array which we called count. 193 194 00:16:31,980 --> 00:16:39,750 So we're putting that value of count inside our

and then we get to trigger the set count which 194 195 00:16:39,750 --> 00:16:43,570 is the function that's going to update the value of count. 195 196 00:16:43,710 --> 00: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 197 00:16:50,340 --> 00:16:51,090 1, 197 198 00:16:51,090 --> 00:16:55,500 so it increases it by 1 each time. 198 199 00:16:55,500 --> 00:17:01,620 Now the idea of hooks might be quite unfamiliar to you but once you wrap your head around its mechanism 199 200 00:17:02,070 --> 00:17:08,800 it's incredibly powerful and really useful when you want to create any sort of interactive app. 200 201 00:17:08,820 --> 00: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 202 00:17:13,320 --> 00: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 203 00:17:20,220 --> 00:17:27,600 code sandbox right now and then to recreate this app from scratch yourself. So delete everything that's 203 204 00:17:27,600 --> 00:17:35,190 inside App.js and refresh yourself just simply on the syntax to begin with because it looks pretty 204 205 00:17:35,190 --> 00:17:42,060 weird. And in the next lesson I've got a another challenge for you to implement this use 205 206 00:17:42,100 --> 00:17:42,940 State hook. 206 207 00:17:42,990 --> 00:17:45,420 So you're going to be getting plenty of practice 207 208 00:17:45,600 --> 00:17:50,320 and we're also going to be talking about destructuring a little bit later on as well. 208 209 00:17:50,430 --> 00: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 210 00:17:55,950 --> 00:18:01,710 scratch yourself without looking at the video and be able to understand how we actually got here in 210 211 00:18:01,710 --> 00:18:02,940 the first place. 211 212 00:18:03,030 --> 00: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.