Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranรฎ)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
Well, this certainly costs some performance.
Of course, we got ongoing function executions.
We got a virtual comparison.
It's needless to say that React is highly optimized
for those executions and comparisons.
So in a lot of apps,
and especially in simple apps like this one,
this will absolutely not matter.
Nonetheless, in bigger apps,
you might want to optimize that.
And, therefore, you as a developer can tell React
that it should only re-execute this DemoOutput component
under certain circumstances.
And those circumstances would be
that the props, which this component received,
changed, for example.
So that if I bring back show={false} here,
React actually checks if the show value changed,
and only if that's the case, it will re-execute DemoOutput.
That might be closer to the behavior we want.
How can we tell React that it should behave like this?
Well, we have to go to the component
for which we wanna opt into that did the prop change check.
And we simply wrap our component,
for example, here in the export line with React.memo.
This is for functional components.
For class-based components, this does not work.
But I'll take a closer look at class-based components
and how to optimize those
in the class-based component section
later down in the course.
Since we can basically work with only functional components,
class-based components are not the focus here.
So React.memo allows us to optimize functional components.
Now, what does memo do?
It tells React that for this component,
which it gets as a argument,
React should look at the props this component gets
and check the new value for all those props
and compare it to the previous value those props got.
And only if the value of a prop changed,
the component should be re-executed and re-evaluated.
And if the parent component changed
but the prop values for that component here did not change,
component execution will be skipped.
If we wrap this and we save it,
we can see the result of that by going back.
Initially, of course, DemoOutput is executed
because the App was just rendered for the first time.
But now if we clear the console, if I click this button,
you see only APP and Button RUNNING is being printed.
The DemoOutput RUNNING is not being printed,
and therefore MyParagraph RUNNING
is also not being printed
because MyParagraph is a child of DemoOutput.
And if DemoOutput is not re-executed,
of course, its child is also not re-executed.
So this is now an optimization in place here
that avoids this unnecessary re-rendering.
Now, that might bring up a new question, though:
Why aren't we using that on all components
if it allows us to optimize them?
Because this optimization comes at a cost.
The memo method here tells React
that whenever the App component changed,
it should go to this component here
and compare the new prop values to the previous prop values,
so therefore React needs to do two things.
It needs to store the previous prop values,
and it needs to make that comparison.
And that, of course, also has its own performance cost.
And it, therefore, greatly depends
on the component you're applying this to
whether it's worth it or not
because you're trading the performance cost
of re-evaluating the component
for the performance cost of comparing props.
And it's impossible to say which cost is higher
because it depends on the number of props you have
and on the complexity of your component
and the number of child components your component has.
Of course, React.memo can be a great tool
if you have a huge component tree
with a lot of child components.
And on a high level in the component tree,
you can avoid unnecessary re-render cycles
for the entire branch of the component tree.
Like in this case,
by avoiding the re-evaluation of DemoOutput,
we're also automatically avoiding
the re-evaluation of MyParagraph
even though we're not using React Demo in there
just because we cut off this entire branch,
so this entire branch of the component tree.
That is something
where React.memo can definitely be worth it.
If you, on the other hand, have a component
where you know it's going to change
or its props values are going to change
with pretty much every re-evaluation
of the parent component anyways,
then React.memo doesn't make a lot of sense
because if the result
is that the component should re-render anyways,
well, then you can also save that extra comparison
of the prop values.
That's then just some overhead cost, which is not worth it.
And, of course, ultimately, as always,
it depends on your app size.
For small apps, for small component trees, and so on,
for all of that, it might simply not worth it to add this.
But for larger apps where you can cut off entire branches
of unnecessary re-evaluations,
it might very well be worth it.
You just don't wanna wrap every component with React.memo.
Instead, you wanna pick some key parts
in your component tree which allows you to cut off
an entire branch of child components.
That's way more effective
than doing this on every child component.
So now that we learned about React.memo,
let's also apply it to the Button.
We can argue whether that's good or not
because the Button is a trigger component,
so doing that prop-checking might not be worth it.
On the other hand, we as a developer know
that this Button realistically doesn't re-change,
so re-evaluating the Button all the time
shouldn't be worth it.
There's nothing on it that changes, right?
We have the same text, we have the same function,
so why don't we wrap it?
For that, let's go to Button and use React.memo down here
and wrap our Button component with it.
Now, you will see something interesting if you do that.
If you save that and reload the app,
of course, initially, we see Button RUNNING.
But now if we click Toggle Paragraph,
we, again, see Button RUNNING.
Why is that happening? That makes no sense, right?
Well, we see Button RUNNING again and again
because, actually, its prop values did change.
That's strange, right?
If we have a look at that, it only gets one prop, onClick,
or, actually, two props, the children here,
but both prop values never change.
We always have the same text,
and we always have the same function, right?
Well, this is one of the most common gotchas with React.
Keep in mind that this App component
is just a function in the end,
and it re-executes like a normal JavaScript function
because it is a normal JavaScript function
if your state changes.
The only magic thing here
is that the function's going to be called by React
and not by you.
But then, it still executes like a normal function,
which means all that code executes again,
and that has one important implication.
Of course, this function
which you pass to the Button is re-created.
This is now a brand new function for every render
or every execution cycle of the App function
because in the end it's just a normal constant
which we recreate.
All that code in here is executed again,
so, of course, a new function is created.
This is not the same function all the time.
It's a function that does the same thing.
But technically to JavaScript, it's a brand new function
for every time the App function is being executed.
That's, by the way, also true
for false being passed to DemoOutput.
Previously, I said that this never changes,
even that technically was not correct.
This App function is re-executed,
therefore a new false value is created.
So even if we had false in the last render cycle too,
now we have a new false.
But if that's the case, why does React.memo then work
on the DemoOutput but not on the button?
What's the difference between false and the function here?
If a new false is created and a new function is created,
shouldn't then both components be re-evaluated?
Well, for that, you have to keep in mind
that false is a boolean,
and booleans like strings and numbers
are primitive values in JavaScript.
Now, what React.memo does in the end
is it has a look at all the prop values,
and in the end it compares props.show
to props.previous.show, you could say.
This is not exactly what it does internally,
but you can imagine it like that.
So in the end it has a look
at the previous value for the show prop
and compares it to the current value,
and it does so with a regular comparison operator.
Now, for primitive values, that will work
because for primitive values, if I compare two booleans,
I get true if they are the same.
If I compare two strings, I get true if they are the same.
Now, technically, that is a different boolean
than this here,
and that's a different string than this.
These are two different values.
But for primitive values, this comparison works.
Now, that's not true
if you compare arrays or objects or functions.
For comparing two arrays, let's say,
which look similar to us humans,
in JavaScript they are not equal.
And that's not React-specific, that is JavaScript.
And attached to this lecture, you find an article
and a video on primitive and reference values
so that you really understand this
because that's a core concept of JavaScript.
Now, it's important to understand
that functions are just objects in JavaScript.
Again, not React-specific, that's just JavaScript.
So here a new function object is created
with every time the App function runs,
and this function object is passed to the onClick prop.
Now, therefore, Button in the end compares props.onClick
to props.previous.onClick, for example.
And in there we have two function objects.
Now, two objects, even if they have the same content,
are never equal in JavaScript when compared like this.
And, therefore, React.memo finds out that the value changed
just because of how JavaScript works.
Now, that is really important to understand.
I know it's a common gotcha
and something a lot of developers,
even more experienced ones, are struggling with.
That's why I'm emphasizing it like this.
This is crucial to understand and to get right.
Now, of course, as a result of that,
does this mean that React.memo is useless
for components that receive objects
or arrays or functions through their props?
No, thankfully not.
Let's have a look at the solution in the next lecture.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.