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.