All language subtitles for 005 Preventing Unnecessary Re-Evaluations with React.memo()_en

af Afrikaans
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bn Bengali
bs Bosnian
bg Bulgarian
ca Catalan
ceb Cebuano
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
tl Filipino
fi Finnish
fr French
fy Frisian
gl Galician
ka Georgian
de German
el Greek
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
km Khmer
ko Korean
ku Kurdish (Kurmanji)
ky Kyrgyz
lo Lao
la Latin
lv Latvian
lt Lithuanian
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mn Mongolian
my Myanmar (Burmese)
ne Nepali
no Norwegian
ps Pashto
fa Persian Download
pl Polish
pt Portuguese
pa Punjabi
ro Romanian
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
st Sesotho
sn Shona
sd Sindhi
si Sinhala
sk Slovak
sl Slovenian
so Somali
es Spanish
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
te Telugu
th Thai
tr Turkish
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu
or Odia (Oriya)
rw Kinyarwanda
tk Turkmen
tt Tatar
ug Uyghur
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.