Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:02,220 --> 00:00:05,410
Well, this certainly costs some performance.
2
00:00:05,410 --> 00:00:08,240
Of course, we got ongoing function executions.
3
00:00:08,240 --> 00:00:10,220
We got a virtual comparison.
4
00:00:10,220 --> 00:00:13,360
It's needless to say that React is highly optimized
5
00:00:13,360 --> 00:00:15,710
for those executions and comparisons.
6
00:00:15,710 --> 00:00:17,410
So in a lot of apps,
7
00:00:17,410 --> 00:00:20,420
and especially in simple apps like this one,
8
00:00:20,420 --> 00:00:22,470
this will absolutely not matter.
9
00:00:22,470 --> 00:00:24,080
Nonetheless, in bigger apps,
10
00:00:24,080 --> 00:00:25,970
you might want to optimize that.
11
00:00:25,970 --> 00:00:30,030
And, therefore, you as a developer can tell React
12
00:00:30,030 --> 00:00:34,250
that it should only re-execute this DemoOutput component
13
00:00:34,250 --> 00:00:37,530
under certain circumstances.
14
00:00:37,530 --> 00:00:39,980
And those circumstances would be
15
00:00:39,980 --> 00:00:43,550
that the props, which this component received,
16
00:00:43,550 --> 00:00:45,760
changed, for example.
17
00:00:45,760 --> 00:00:48,800
So that if I bring back show={false} here,
18
00:00:48,800 --> 00:00:51,680
React actually checks if the show value changed,
19
00:00:51,680 --> 00:00:55,270
and only if that's the case, it will re-execute DemoOutput.
20
00:00:55,270 --> 00:00:57,933
That might be closer to the behavior we want.
21
00:00:58,870 --> 00:01:01,880
How can we tell React that it should behave like this?
22
00:01:01,880 --> 00:01:03,670
Well, we have to go to the component
23
00:01:03,670 --> 00:01:08,080
for which we wanna opt into that did the prop change check.
24
00:01:08,080 --> 00:01:10,860
And we simply wrap our component,
25
00:01:10,860 --> 00:01:15,860
for example, here in the export line with React.memo.
26
00:01:19,150 --> 00:01:21,610
This is for functional components.
27
00:01:21,610 --> 00:01:23,880
For class-based components, this does not work.
28
00:01:23,880 --> 00:01:26,560
But I'll take a closer look at class-based components
29
00:01:26,560 --> 00:01:28,250
and how to optimize those
30
00:01:28,250 --> 00:01:30,380
in the class-based component section
31
00:01:30,380 --> 00:01:31,820
later down in the course.
32
00:01:31,820 --> 00:01:35,060
Since we can basically work with only functional components,
33
00:01:35,060 --> 00:01:38,080
class-based components are not the focus here.
34
00:01:38,080 --> 00:01:42,380
So React.memo allows us to optimize functional components.
35
00:01:42,380 --> 00:01:44,280
Now, what does memo do?
36
00:01:44,280 --> 00:01:47,610
It tells React that for this component,
37
00:01:47,610 --> 00:01:50,390
which it gets as a argument,
38
00:01:50,390 --> 00:01:54,230
React should look at the props this component gets
39
00:01:54,230 --> 00:01:58,140
and check the new value for all those props
40
00:01:58,140 --> 00:02:00,930
and compare it to the previous value those props got.
41
00:02:00,930 --> 00:02:03,320
And only if the value of a prop changed,
42
00:02:03,320 --> 00:02:06,560
the component should be re-executed and re-evaluated.
43
00:02:06,560 --> 00:02:08,639
And if the parent component changed
44
00:02:08,639 --> 00:02:12,510
but the prop values for that component here did not change,
45
00:02:12,510 --> 00:02:15,093
component execution will be skipped.
46
00:02:17,120 --> 00:02:18,720
If we wrap this and we save it,
47
00:02:18,720 --> 00:02:21,810
we can see the result of that by going back.
48
00:02:21,810 --> 00:02:24,600
Initially, of course, DemoOutput is executed
49
00:02:24,600 --> 00:02:27,830
because the App was just rendered for the first time.
50
00:02:27,830 --> 00:02:30,700
But now if we clear the console, if I click this button,
51
00:02:30,700 --> 00:02:34,700
you see only APP and Button RUNNING is being printed.
52
00:02:34,700 --> 00:02:37,460
The DemoOutput RUNNING is not being printed,
53
00:02:37,460 --> 00:02:39,590
and therefore MyParagraph RUNNING
54
00:02:39,590 --> 00:02:41,000
is also not being printed
55
00:02:41,000 --> 00:02:43,820
because MyParagraph is a child of DemoOutput.
56
00:02:43,820 --> 00:02:46,330
And if DemoOutput is not re-executed,
57
00:02:46,330 --> 00:02:50,130
of course, its child is also not re-executed.
58
00:02:50,130 --> 00:02:52,920
So this is now an optimization in place here
59
00:02:52,920 --> 00:02:56,550
that avoids this unnecessary re-rendering.
60
00:02:56,550 --> 00:02:59,190
Now, that might bring up a new question, though:
61
00:02:59,190 --> 00:03:02,660
Why aren't we using that on all components
62
00:03:02,660 --> 00:03:04,543
if it allows us to optimize them?
63
00:03:05,490 --> 00:03:09,440
Because this optimization comes at a cost.
64
00:03:09,440 --> 00:03:12,540
The memo method here tells React
65
00:03:12,540 --> 00:03:15,290
that whenever the App component changed,
66
00:03:15,290 --> 00:03:17,520
it should go to this component here
67
00:03:17,520 --> 00:03:21,610
and compare the new prop values to the previous prop values,
68
00:03:21,610 --> 00:03:24,140
so therefore React needs to do two things.
69
00:03:24,140 --> 00:03:26,560
It needs to store the previous prop values,
70
00:03:26,560 --> 00:03:28,940
and it needs to make that comparison.
71
00:03:28,940 --> 00:03:31,740
And that, of course, also has its own performance cost.
72
00:03:31,740 --> 00:03:34,290
And it, therefore, greatly depends
73
00:03:34,290 --> 00:03:36,800
on the component you're applying this to
74
00:03:36,800 --> 00:03:38,840
whether it's worth it or not
75
00:03:38,840 --> 00:03:41,680
because you're trading the performance cost
76
00:03:41,680 --> 00:03:43,660
of re-evaluating the component
77
00:03:43,660 --> 00:03:46,570
for the performance cost of comparing props.
78
00:03:46,570 --> 00:03:49,730
And it's impossible to say which cost is higher
79
00:03:49,730 --> 00:03:52,290
because it depends on the number of props you have
80
00:03:52,290 --> 00:03:54,720
and on the complexity of your component
81
00:03:54,720 --> 00:03:58,700
and the number of child components your component has.
82
00:03:58,700 --> 00:04:01,570
Of course, React.memo can be a great tool
83
00:04:01,570 --> 00:04:03,820
if you have a huge component tree
84
00:04:03,820 --> 00:04:05,850
with a lot of child components.
85
00:04:05,850 --> 00:04:08,690
And on a high level in the component tree,
86
00:04:08,690 --> 00:04:11,900
you can avoid unnecessary re-render cycles
87
00:04:11,900 --> 00:04:14,720
for the entire branch of the component tree.
88
00:04:14,720 --> 00:04:15,970
Like in this case,
89
00:04:15,970 --> 00:04:19,480
by avoiding the re-evaluation of DemoOutput,
90
00:04:19,480 --> 00:04:21,760
we're also automatically avoiding
91
00:04:21,760 --> 00:04:24,340
the re-evaluation of MyParagraph
92
00:04:24,340 --> 00:04:27,060
even though we're not using React Demo in there
93
00:04:27,060 --> 00:04:30,170
just because we cut off this entire branch,
94
00:04:30,170 --> 00:04:33,650
so this entire branch of the component tree.
95
00:04:33,650 --> 00:04:34,483
That is something
96
00:04:34,483 --> 00:04:37,700
where React.memo can definitely be worth it.
97
00:04:37,700 --> 00:04:40,080
If you, on the other hand, have a component
98
00:04:40,080 --> 00:04:42,500
where you know it's going to change
99
00:04:42,500 --> 00:04:44,860
or its props values are going to change
100
00:04:44,860 --> 00:04:47,000
with pretty much every re-evaluation
101
00:04:47,000 --> 00:04:48,950
of the parent component anyways,
102
00:04:48,950 --> 00:04:51,410
then React.memo doesn't make a lot of sense
103
00:04:51,410 --> 00:04:52,790
because if the result
104
00:04:52,790 --> 00:04:55,950
is that the component should re-render anyways,
105
00:04:55,950 --> 00:04:58,570
well, then you can also save that extra comparison
106
00:04:58,570 --> 00:04:59,890
of the prop values.
107
00:04:59,890 --> 00:05:03,750
That's then just some overhead cost, which is not worth it.
108
00:05:03,750 --> 00:05:05,660
And, of course, ultimately, as always,
109
00:05:05,660 --> 00:05:07,350
it depends on your app size.
110
00:05:07,350 --> 00:05:10,630
For small apps, for small component trees, and so on,
111
00:05:10,630 --> 00:05:14,180
for all of that, it might simply not worth it to add this.
112
00:05:14,180 --> 00:05:17,530
But for larger apps where you can cut off entire branches
113
00:05:17,530 --> 00:05:19,910
of unnecessary re-evaluations,
114
00:05:19,910 --> 00:05:21,760
it might very well be worth it.
115
00:05:21,760 --> 00:05:25,250
You just don't wanna wrap every component with React.memo.
116
00:05:25,250 --> 00:05:28,080
Instead, you wanna pick some key parts
117
00:05:28,080 --> 00:05:31,280
in your component tree which allows you to cut off
118
00:05:31,280 --> 00:05:34,150
an entire branch of child components.
119
00:05:34,150 --> 00:05:35,840
That's way more effective
120
00:05:35,840 --> 00:05:39,010
than doing this on every child component.
121
00:05:39,010 --> 00:05:40,890
So now that we learned about React.memo,
122
00:05:40,890 --> 00:05:42,650
let's also apply it to the Button.
123
00:05:42,650 --> 00:05:45,130
We can argue whether that's good or not
124
00:05:45,130 --> 00:05:47,180
because the Button is a trigger component,
125
00:05:47,180 --> 00:05:50,270
so doing that prop-checking might not be worth it.
126
00:05:50,270 --> 00:05:52,120
On the other hand, we as a developer know
127
00:05:52,120 --> 00:05:55,590
that this Button realistically doesn't re-change,
128
00:05:55,590 --> 00:05:58,140
so re-evaluating the Button all the time
129
00:05:58,140 --> 00:05:59,320
shouldn't be worth it.
130
00:05:59,320 --> 00:06:01,890
There's nothing on it that changes, right?
131
00:06:01,890 --> 00:06:03,960
We have the same text, we have the same function,
132
00:06:03,960 --> 00:06:05,893
so why don't we wrap it?
133
00:06:07,090 --> 00:06:11,570
For that, let's go to Button and use React.memo down here
134
00:06:12,910 --> 00:06:16,040
and wrap our Button component with it.
135
00:06:16,040 --> 00:06:19,143
Now, you will see something interesting if you do that.
136
00:06:20,860 --> 00:06:23,380
If you save that and reload the app,
137
00:06:23,380 --> 00:06:25,710
of course, initially, we see Button RUNNING.
138
00:06:25,710 --> 00:06:28,060
But now if we click Toggle Paragraph,
139
00:06:28,060 --> 00:06:31,570
we, again, see Button RUNNING.
140
00:06:31,570 --> 00:06:35,583
Why is that happening? That makes no sense, right?
141
00:06:36,700 --> 00:06:39,560
Well, we see Button RUNNING again and again
142
00:06:39,560 --> 00:06:43,483
because, actually, its prop values did change.
143
00:06:44,470 --> 00:06:45,410
That's strange, right?
144
00:06:45,410 --> 00:06:48,850
If we have a look at that, it only gets one prop, onClick,
145
00:06:48,850 --> 00:06:51,890
or, actually, two props, the children here,
146
00:06:51,890 --> 00:06:54,830
but both prop values never change.
147
00:06:54,830 --> 00:06:56,180
We always have the same text,
148
00:06:56,180 --> 00:06:58,540
and we always have the same function, right?
149
00:06:58,540 --> 00:07:03,170
Well, this is one of the most common gotchas with React.
150
00:07:03,170 --> 00:07:05,860
Keep in mind that this App component
151
00:07:05,860 --> 00:07:07,840
is just a function in the end,
152
00:07:07,840 --> 00:07:11,380
and it re-executes like a normal JavaScript function
153
00:07:11,380 --> 00:07:14,090
because it is a normal JavaScript function
154
00:07:14,090 --> 00:07:15,860
if your state changes.
155
00:07:15,860 --> 00:07:18,510
The only magic thing here
156
00:07:18,510 --> 00:07:21,050
is that the function's going to be called by React
157
00:07:21,050 --> 00:07:22,440
and not by you.
158
00:07:22,440 --> 00:07:25,380
But then, it still executes like a normal function,
159
00:07:25,380 --> 00:07:28,100
which means all that code executes again,
160
00:07:28,100 --> 00:07:30,710
and that has one important implication.
161
00:07:30,710 --> 00:07:31,970
Of course, this function
162
00:07:31,970 --> 00:07:35,220
which you pass to the Button is re-created.
163
00:07:35,220 --> 00:07:38,550
This is now a brand new function for every render
164
00:07:38,550 --> 00:07:42,230
or every execution cycle of the App function
165
00:07:42,230 --> 00:07:44,580
because in the end it's just a normal constant
166
00:07:44,580 --> 00:07:45,833
which we recreate.
167
00:07:47,600 --> 00:07:50,570
All that code in here is executed again,
168
00:07:50,570 --> 00:07:54,310
so, of course, a new function is created.
169
00:07:54,310 --> 00:07:56,600
This is not the same function all the time.
170
00:07:56,600 --> 00:07:59,060
It's a function that does the same thing.
171
00:07:59,060 --> 00:08:02,940
But technically to JavaScript, it's a brand new function
172
00:08:02,940 --> 00:08:06,033
for every time the App function is being executed.
173
00:08:07,570 --> 00:08:08,870
That's, by the way, also true
174
00:08:08,870 --> 00:08:11,640
for false being passed to DemoOutput.
175
00:08:11,640 --> 00:08:13,940
Previously, I said that this never changes,
176
00:08:13,940 --> 00:08:16,700
even that technically was not correct.
177
00:08:16,700 --> 00:08:19,170
This App function is re-executed,
178
00:08:19,170 --> 00:08:22,410
therefore a new false value is created.
179
00:08:22,410 --> 00:08:25,690
So even if we had false in the last render cycle too,
180
00:08:25,690 --> 00:08:27,630
now we have a new false.
181
00:08:27,630 --> 00:08:31,230
But if that's the case, why does React.memo then work
182
00:08:31,230 --> 00:08:33,250
on the DemoOutput but not on the button?
183
00:08:33,250 --> 00:08:36,659
What's the difference between false and the function here?
184
00:08:36,659 --> 00:08:40,429
If a new false is created and a new function is created,
185
00:08:40,429 --> 00:08:44,960
shouldn't then both components be re-evaluated?
186
00:08:44,960 --> 00:08:46,690
Well, for that, you have to keep in mind
187
00:08:46,690 --> 00:08:48,598
that false is a boolean,
188
00:08:48,598 --> 00:08:52,050
and booleans like strings and numbers
189
00:08:52,050 --> 00:08:54,910
are primitive values in JavaScript.
190
00:08:54,910 --> 00:08:57,450
Now, what React.memo does in the end
191
00:08:57,450 --> 00:09:00,560
is it has a look at all the prop values,
192
00:09:00,560 --> 00:09:05,560
and in the end it compares props.show
193
00:09:05,560 --> 00:09:09,110
to props.previous.show, you could say.
194
00:09:09,110 --> 00:09:11,100
This is not exactly what it does internally,
195
00:09:11,100 --> 00:09:13,240
but you can imagine it like that.
196
00:09:13,240 --> 00:09:14,240
So in the end it has a look
197
00:09:14,240 --> 00:09:15,950
at the previous value for the show prop
198
00:09:15,950 --> 00:09:17,650
and compares it to the current value,
199
00:09:17,650 --> 00:09:21,523
and it does so with a regular comparison operator.
200
00:09:23,450 --> 00:09:26,150
Now, for primitive values, that will work
201
00:09:26,150 --> 00:09:31,070
because for primitive values, if I compare two booleans,
202
00:09:31,070 --> 00:09:33,340
I get true if they are the same.
203
00:09:33,340 --> 00:09:37,540
If I compare two strings, I get true if they are the same.
204
00:09:37,540 --> 00:09:39,593
Now, technically, that is a different boolean
205
00:09:39,593 --> 00:09:40,550
than this here,
206
00:09:40,550 --> 00:09:42,380
and that's a different string than this.
207
00:09:42,380 --> 00:09:44,170
These are two different values.
208
00:09:44,170 --> 00:09:47,560
But for primitive values, this comparison works.
209
00:09:47,560 --> 00:09:48,750
Now, that's not true
210
00:09:48,750 --> 00:09:52,600
if you compare arrays or objects or functions.
211
00:09:52,600 --> 00:09:55,290
For comparing two arrays, let's say,
212
00:09:55,290 --> 00:09:58,293
which look similar to us humans,
213
00:09:59,690 --> 00:10:03,860
in JavaScript they are not equal.
214
00:10:03,860 --> 00:10:06,580
And that's not React-specific, that is JavaScript.
215
00:10:06,580 --> 00:10:09,470
And attached to this lecture, you find an article
216
00:10:09,470 --> 00:10:12,210
and a video on primitive and reference values
217
00:10:12,210 --> 00:10:13,790
so that you really understand this
218
00:10:13,790 --> 00:10:17,360
because that's a core concept of JavaScript.
219
00:10:17,360 --> 00:10:19,500
Now, it's important to understand
220
00:10:19,500 --> 00:10:23,210
that functions are just objects in JavaScript.
221
00:10:23,210 --> 00:10:27,260
Again, not React-specific, that's just JavaScript.
222
00:10:27,260 --> 00:10:30,130
So here a new function object is created
223
00:10:30,130 --> 00:10:32,430
with every time the App function runs,
224
00:10:32,430 --> 00:10:36,630
and this function object is passed to the onClick prop.
225
00:10:36,630 --> 00:10:41,630
Now, therefore, Button in the end compares props.onClick
226
00:10:41,810 --> 00:10:45,960
to props.previous.onClick, for example.
227
00:10:45,960 --> 00:10:48,710
And in there we have two function objects.
228
00:10:48,710 --> 00:10:52,040
Now, two objects, even if they have the same content,
229
00:10:52,040 --> 00:10:55,470
are never equal in JavaScript when compared like this.
230
00:10:55,470 --> 00:10:59,720
And, therefore, React.memo finds out that the value changed
231
00:10:59,720 --> 00:11:03,130
just because of how JavaScript works.
232
00:11:03,130 --> 00:11:05,130
Now, that is really important to understand.
233
00:11:05,130 --> 00:11:07,670
I know it's a common gotcha
234
00:11:07,670 --> 00:11:09,480
and something a lot of developers,
235
00:11:09,480 --> 00:11:12,090
even more experienced ones, are struggling with.
236
00:11:12,090 --> 00:11:14,570
That's why I'm emphasizing it like this.
237
00:11:14,570 --> 00:11:18,730
This is crucial to understand and to get right.
238
00:11:18,730 --> 00:11:20,570
Now, of course, as a result of that,
239
00:11:20,570 --> 00:11:23,850
does this mean that React.memo is useless
240
00:11:23,850 --> 00:11:26,040
for components that receive objects
241
00:11:26,040 --> 00:11:29,120
or arrays or functions through their props?
242
00:11:29,120 --> 00:11:30,563
No, thankfully not.
243
00:11:31,780 --> 00:11:34,480
Let's have a look at the solution in the next lecture.
19499
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.