So many of you are using useEffect completely
wrong in your applications. So much so that even on a useMemo tutorial video that I did a
while ago that has nothing to do with useEffect, the most common comment that I get is, can I use
useEffect instead? No, you cannot. Stop trying to use useEffect for everything. useEffect is not
supposed to be used for everything. It's supposed to be used very rarely in a React application.
And so many of you are using it for every single reason that you can find. And honestly, it's
leading to a lot of bugs in your applications. So in this video, I hope to finally be able to
clear this up and teach you how to correctly use useEffect and when to not use useEffect. Let's
talk about it. So let's actually take the useMemo example, because it honestly baffles me that
people are seriously considering using useEffect for this. So what we have here is we have a
component called the app component. And we have one piece of state over here for the items. This
component also receives the filter through props and the filters are defined here. It's basically
an object that has an optional search property of type string. And then we have filtered items
over here, which is built using useMemo. And all that this is doing is it's taken the items taken
the filters, calling the filter items function with the items in the filters, and then just
returning the items that are currently filtered. And then we're passing filters and items in the
dependency array of the useMemo. That's it. Now this is perfectly fine. And this is actually the
correct way to do it. And if you're not familiar with this, if you're not familiar with useMemo and
how it works, please go and check out the tutorial video that I did on useMemo, because that is
going to explain everything accurately. However, multiple developers have commented and
even insisted that this is incorrect, and that actually, we should be using useEffect
instead, what they argue is that we should get rid of filtered items here, and instead put it
as a state variable, and then use useEffect to manually manage it, right. So let's do it. Let's
come here, let's remove filtered items, let's do const filtered items, set filtered items, that is
going to be equal to useState. And we're going to pass this an array. And then we're going to come
here and create a useEffect. So we're going to do useEffect, import this from React, give it a
function over here. And then here, we're going to do set filtered items. And we're going to do get
what is filter items. And then we're going to pass items and then filters like so. And then we need
to provide a dependency array, which we're going to do filters, and then items like so. And then
here we have a type error, which we can easily fix because the types are not matching, we just have
to type our state here. So we can do string and then an array of strings. And then we can close
this. And let's do the same thing for this one, just to have it be consistent string, and then
close this. And now we have no more errors. So this is what developers are recommending that
we do instead. Now, first of all, what I want to say is that this actually works, right, this is
functionally equivalent to how we had it before, we're going to have the same filtered items, and
they're going to be updated in the same way with the same values as we had it before. But just
because this is functionally equivalent to how we had it before, doesn't mean that it's better,
or even more importantly, that you should use it. Because if you really think about it, how is
this component going to render, right, let's take the initial render, right, this component
is going to be rendered for the first time, it's going to have items here, which is going to
be an empty array. And then it's also going to have filtered items, which is also going to be an
empty array, right. So that's what's going to end up showing in the actual UI initially on the first
render. And then this use effect is going to run, it's going to actually get the filtered items from
this function. And then it's going to set them in the state, which is going to trigger a rerender of
this component and update. And only then on that second render, are you actually going to see the
correct filtered items on the JSX on the screen, right. So this is doing the same thing as we had
it before, but in two render passes. So initially, on the first render, we're actually rendering
the component with stale data. Because let's say for example, that we actually had a value
for the search initially on mount when this component mounted search was something, we will
not show that search in the actual filtered items. Because that only happens afterwards when this use
effect is run, which is only going to show up on the second render of this component. So not only
are we actually doing two renders, which is worse for performance, but we're actually rendering the
first time with incorrect data. And sometimes you might actually see a flicker in the application,
which I'm sure that you've seen in your own applications or in some other applications. This
is a common pitfall of react. And it happens when you use this effect when you shouldn't do right if
you compare this to how we had it before with use memo. So let's go back and let's undo all of these
things. Let's put them here. Now with use memo, we actually don't need to manage anything ourselves,
we just declared filtered items, we just made it equal to return filtered items based on the items
in the filters. And as long as we pass this in the dependency array, this is always going to
be accurate given the filters and the items, especially on the first render. If we have a
search here on the first render, that search is going to be inside of this filters. And it's
going to be get taken into account here without triggering a whole rerender of the components
that is more performant. And we don't even need to worry about this at all. With this, we actually
never need to touch filtered items again, unless we want to change the logic of how it's actually
computed. As long as we have items and filters, and whenever they change, this is always going to
be kept up to date without triggering a rerender of the component. So this is more performant. And
this is the correct way to do it not by using use effect. And this is actually always what I try
to teach you in every single one of my videos, I always try to teach you the correct way of doing
something. And I always try my best to explain to you why we're doing it that way, as opposed to
doing it another way, right. So I hope that now this is clear that in this case, you have to
use use memo and not use effect because it's better for multiple reasons. Let's now look at
another example that I see very often in react applications. And also a lot of developers think
that this is correct, this is actually worse than the first example, that is a chain of use effects.
So over here, what we have is we have a card game, we just don't have the actual UI for it. But you
can imagine that this would be a sort of a card game, we have a state here for the cart, which
can have a property of is called if this card is a gold card, it's a special card. And then we have
a bunch of use effects that basically are chained together and react to manipulating that card piece
of state. So first, we have this use effect over here, which listens to cart. So whenever we have
a cart, which can be no or actually have a card value, whenever we have a cart, we're basically
checking if the card has gold. And if it has gold, we're updating the gold card count state variable,
this one here, and setting it incrementing it by one. Then once that happens, we have this use
effect over here, which is listening to gold card count the state variable that we just updated. And
it's checking if this one is greater than three, then it's updating the round setting the round
to round plus one, and then resetting the gold card count simulating a new round, you have gold
card count zero, and you can start all over again, then we have another use effect, which listens
to round and then if the round is over than five, it's going to set is game over to true,
which then as a bonus, if that wasn't enough, has another use effect that listens to is game
over. And that will alert the browser and say good game and simulate the actual ending of
a game. This as you can hopefully realize, please is a giant mess, right? There are a total
of four use effects over here, each listening to a different part of the state, each triggering their
own updates and trying to sync everything together to make something that is cohesively trying to be
a game. I mean, don't get me wrong, this works, right? This is functionally functional, it
works. And you're going to have a game but it doesn't necessarily mean they're going to have
a performing game that has the best code and the best implementation execution of that specific
game, right? Like this is a nightmare to maintain, trust me, I've seen a lot of projects that adopt
this pattern, this is so difficult to maintain, because it's so hard to track all of these
different updates, right? You have basically one update here that triggers this one, which
triggered this one and triggers this one, right? This is a mess to maintain. And all not only that,
but also the performance implication, every time that you set a cart, you're basically triggering
this effect, which is going to update one state that's going to trigger a rerun of the component
that is then going to trigger this use effect, which is going to set another update and trigger
another rerun of the component, which is then going to set this use effect, and it's also going
to rerender the component. So every single time that you set a card, you have multiple updates
in your component. And that is going to lead to horrible performance. And what's even worse is
that just like in the first example of this video, you actually don't need use effect to make all
of this work, you can actually do the exact same thing without using any use effect. And actually
with using less state variables than what we have now, let me show you. So what we're going to do
is we're going to come here below all of these effects. And we're going to create a new function,
we're going to do function handle place next card, like so this is going to take one argument,
the next card, so we're going to the next card, and it's going to be of type cart like so this
function will essentially try to do all of these things here in one function without having all of
these use effects. And without having to rerun the component multiple times just to achieve the same
functionality. So the first thing that we're going to want to do is pretty simple, we're just going
to do set cart and then next card like so right, whenever we place a new card, we actually want
to set it in the state and have that update be reflected because we're using it in the JSX
probably, which again is not written here. But you can imagine that we will do that, then
instead of having this use effect over here, which first checks if the card is not null,
because this card can be null. And then if the card is gold, first of all, in this function
over here, next card is not going to be null. So we can forget about checking for this because
we're only going to have this function be called if we actually have a cart. So we don't need to
worry about that. But then we can directly just take card that is gold. And then we can actually
render all of this here and actually increment the gold card count. But what we can also do is we
can combine it with this use effect over here, because this one checks if the gold card count is
greater than three. And then we'll also update the round and then set and reset, sorry, the gold
card count. So we can put all of these together in one place and get rid of both of these use
effects over here, which is great. So what we're going to do is we're going to come here and we're
first going to do if next card dot is gold, right, this is going to simulate this first use effect
over here, if card is gold, then we're just going to copy this so that we have it handy, then we're
going to make a second check. And we're going to do over here if gold card count is smaller or
equal to three. And the reason why we're doing smaller or equal to three is because we want to
get rid of this use effect over here.And finally, the only functionality that we need to have is
these two use effects over here. So if the round is greater than five, we set isGameOver
to true. And then if isGameOver is true, we actually alert a good game. But actually, do
we really need isGameOver? Because if the round is greater than five, we can just directly alert the
browser with the same thing. So we can actually get rid of isGameOver, right? We can get rid of
it. And then we can just take this code here, if round five, and actually, I'm not going to
copy it, I'm just going to write it manually, because there's a difference, we're going to do
if round is equal, equal, equal to five, because here in this use effect, right, we're checking if
round is greater than five. The only reason we're checking is greater than is because this is going
to run after it's going to run on the next render. But here, and the next render being whenever the
cart is updated, but here, this update, this set cart hasn't yet happened, because we're still in
the context of the previous render, right? So in the previous render, we have to check round equals
equals five, instead of over than five, because we are on the previous render. So if round equals
five, then what we're going to do is just alert, and we're going to put it actually, I'm just going
to copy this code over here, because we do that, and it's gonna be easy. We just alert good game.
And now we actually have the same functionality as we had it before. But it's all in one function.
And more importantly, no use effect is being used, and no component is getting updated, everything
is happening in one pass. And we don't need to wait for updates to trigger different parts of
the code to run, we can put everything in one single function, right? So we actually have
the update here, that's going to set a cart, that's fine. Then we have this if check over here,
we're just going to check next card dot is gold, that is this use effect over here, right? We're
not caring about null, because this cannot be null. And then if card is gold, we're incrementing
here. And we're combining it with this use effect over here, we're checking gold card count greater
than three, here, we're doing lesser or equal than three, we're running this code. Otherwise, if it's
greater than three, we're putting this code. So we can actually get rid of these use effects here,
because we don't need them. Then we're doing if round equals equals five, which is this use effect
over here, but accounting for the fact that we're in the previous renderer, we're not going to set
is game over to true, because we first of all removed it from the state. But second of all,
we didn't need to have it in the first place, we're just going to check if the round is five,
then we're going to do alert good game. And that's it. So that means that we can get rid of this to
use effects here. And now look at our component, it's much smaller, it's much more performant,
and it's doing exactly the same thing. And again, this is a great example of refactoring code,
removing use effects, removing state variables we had is game over before, which we currently don't
have to. So that's one less thing to manage. And our application is much more performant, and it's
doing the exact same thing as we had it before. So in conclusion, if you're thinking about using use
effect in your application, think again, because chances are you probably don't need to. And
there's probably a different way, a better way to achieve the same thing in a much more performant
way. That is a win across the entire board, right, so I hope that with this, I was able to make it
clear enough that use effect is not the solution for everything. And that oftentimes, there is
a better solution. And use effects should only be used very rarely in an application when you
actually have to. And if you want to learn how to correctly use use effect, and more importantly,
no one not to use it and want to actually use it when it makes sense to use it. Check out project
react, which is my react course that is literally going to teach you everything that you need to
know about use effect. And not only that, this course will also teach you how to build a big and
complex application with react that looks exactly like an application that you would see in the real
world. You will literally be guided step by step on everything that you need to know to be able to
build a big application with react and learn all the things that required to make that happen.
I've literally poured my heart and soul into this course. And there's so much content in there.
And the students that are currently on the course are loving it. And it's literally fundamentally
changed the way that they view react and the way that they approach building projects with it. So
if you're interested and you want to learn more, it's called project react and it will be the
first link in the description. And honestly, if you've ever considered taking a react course,
this is the ultimate course, there is no other course like it. And this is the one course that
are going to teach you everything that you could possibly want to know about react. If you enjoyed
this video, and you want to see more videos just like this one, make sure to leave this video a big
thumbs up. You can also click here to subscribe or you can click here to watch a different video
of mine that YouTube seems to think that you're really going to enjoy. And with that being said,
my name has been Darius Cosden. This is Cosden Solutions. Thank you so much for watching, and
I will see you in the next video. Ciao, ciao.