- Yo what is going on guys, welcome back to the channel. My name's Sonny and today
I'm gonna teach you all about the useEffect Hook and why it has transformed the way that we use
functional components and why you need to know it.
♪ I know ♪ ♪ how they love you now ♪ (exciting future bass music) So today's lesson is actually part of the huge React Basics 101 pack. So the React Basics 101
class is full of value and I have been able to do something
incredible for you guys, and that is to actually
release it for absolutely free. Now the only reason that is possible is thanks to the guys over at Skillshare. Skillshare is an online learning community where millions of people come together to take the next step in
their creative journey. The thing I love about Skillshare
is that there are no ads. They're always launching
new premium classes and they also recommend
really interesting classes so before you know it, I'm actually no longer
watching TV or Netflix. All I do is watch Skillshare while I'm actually eating my food. Most classes are under 60 minutes so they should be able
to fit any schedule, whether you're super busy or you've got a little bit
more time on your hands. I've actually gone ahead and dropped the React Basics
101 entire class on Skillshare. The first 1000 people to use
the link in the description are gonna get a free month
worth of Premium Skillshare. And you're gonna be able to with that access the React Basics
which I've uploaded. On top of that you're gonna get access to thousands and thousands of courses available on Skillshare's platform. I've actually been checking out a amazing video editing class
at the moment by Ali Abdaal, where I was actually able to find out how I could use my iPad to
add animated handwriting into my videos to level
up my production value. And now I'm making the
best use out of my iPad as well as leveling up my
Final Cut production game. So this is just an example of the amazing value that I've got since I've signed up at Skillshare. And if you guys wanna go
ahead and benefit from this just like I have, then go ahead and remember the first 1,000 people to
go ahead and grab that link are gonna get a one free
month of Skillshare Premium, which means that you can access
my React Basics 101 class it's completely free. You have nothing to lose. And then after that you
can go ahead and continue if you're enjoying what
you see on Skillshare. If you enjoy the content
that you're seeing then go ahead and smash
the thumbs up button, hit the subscribe and the
bell notification icon so that way you don't miss
any of the future videos without further ado let's roll the React Basics
101 useEffect lesson. Let's do this Pap fam. Peace. Today we're gonna be talking
about the useEffect Hook. Now what is the useEffect Hook
and why is it so important? It's actually one of the core fundamentals when we're using React, we have to understand how
to use a useEffect token. We have to know why it's so powerful and the different use cases of
when we might need to use it. Now what does a useEffect do? A useEffect Hook simply allows us to perform side effects
on a functional component. Now you might be wondering, that sounds pretty cool but I have no idea what
it really means okay? Now in a class based component, you used to have special functions
called lifecycle methods. Okay? So these were things
like componentDidMount, componentDidUnmount, componentWillUpdate and so forth. What this meant was that
whenever the component would sort of reach a lifecycle
point for example, when it mounts, when it's about to render, when it's about to rerender, what happens before the
rerender so when it Unmounts, what happens when it receives new props, all of these things you could tap into and execute a piece of code based on those lifecycle functions. Now previously, you couldn't do this in
functional components and as we know, the whole code base is shifting
to functional components, functional programming. So with that said, the guys over React
introduced the useEffect Hook. Now the useEffect Hook literally replaces every single one of
those lifecycle functions or methods I explained just a second ago. Now we're gonna explain all
of the different use cases. We're gonna break it down. We're gonna make it super simple. Get ready, buckle up, get your coffee. Let's go and jump into the
code without further ado. So what we're gonna be doing here is essentially showing you how
we have the same components, so this is a functional component, this is a class based component
that resembles the same app. And essentially what we
have at the bottom is with a minor difference of an input field, we have a render block over here. So we have the useEffector
Hook with the window width, for an example in just a sec. And over here we have the same example where we basically go ahead
and show the window width but we simply have an
input for demonstration, which I'm gonna show you in just a sec. Okay? So with that said guys
what I'm gonna show you is previously in class based components this is how you would go ahead and tap into those lifecycle
functions that I spoke about. Okay so we had functions like this right? componentDidMount, componentDidUpdate, componentWillUnmount. Now there were some
additional lifecycle functions however these are three of
the most used ones okay? The first one what does that resemble? It resembles when the
component mounts okay? So it's a lifecycle function weld so that we can call a piece of code when the component mounts. For example in this case, we could just console log
the app component loaded. Right now this is very important because imagine you wanted to request
something from a database, you could do it at this point. Now we also wanna run
another piece of code whenever the component updates. So this is where
componentDidUpdate used to come in. However this would run whenever you would basically
get a change in props. This became a bit tricky
when you're using this lifecycle functions so the
useEffect does simplify this and we're gonna go over
that in just a sec. The final one I wanna talk about is the componentWillUnmount now componentWillUnmount is as it sounds before the components about to rerender it unmounts first right? So the lifecycle that you
have to expect is that whenever the page loads, the component renders onto the page and then the user might
interact with the page, which may trigger a rerender. But before the page basically repaints, think of it that way, it unmounts that component and then it puts it
back on the page right? So it has to first mount
the component onto the page. So that way we see it. Then it's gonna receive some kind of interaction or change and that's gonna cause it
to unmount the component and then remount it again. And that's what we see as an update. So that's how we get this interactivity or dynamic behavior with React. So we can actually tap into
the point that it unmounts with the componentWillUnmount
function okay? So these are the three sort
of crucial lifecycle functions that I want you to focus on. Now in functional components it's actually very simple right? So once you understand
that the useEffect Hook, so this one right here, the useEffect Hook it essentially replaces every single lifecycle
function that you may run into okay? So the question is not if
it is capable of doing so, it is capable of doing so. If you have any sort of
concerns and you think, "Hmm I could do this in
a class based component "but I can't do it in a functional." Then believe me you can do
it in a functional component. You can do everything inside
of a functional component now with our handy friend
the useEffect Hook okay? So let's go through a couple
of different variations and what you would use them
for and how they compare to the class based methods
that we just spoke about okay? So we're gonna go ahead and
remove our current drawings and first one is we have the useEffect for triggering on every render okay? So firstly let's understand
how we write the useEffect. So firstly you're gonna have
to import it from React. That's the first typical step. And then what you're gonna
do is type in useEffect okay? Now useEffect takes them some arguments. The first argument is actually a function. Okay so it's an arrow function. And the second one is optional okay so you don't have to
include the second one. And there are reasons for
when you wanna include it and their reasons for when
you don't wanna include it. And this changes the behavior or the point at which
we're tapping into it. So the different lifecycle
functions or points in the component cycle that
I talked about earlier, this will change that behavior
based on the second argument. So here we can pass in something
called a dependency list, right? So it's a dependency array. And simply if we leave it blank
it does a certain behavior. If we put in a variable
it has a certain behavior. And if we leave it blank without
any sort of option there, it has a different behavior. So I'm gonna run through
all of those right now but this is essentially how we write it. So the first example
that I wanna talk about is on every render okay? So if we don't include
that second argument, for example like so, then what we're gonna do is I'm gonna make this a little bit simpler. Let's just go ahead and say
console.log I re-rendered. Right so this will trigger
off every single time, the component rerenders. So imagine we have an input field, you type in it, it's gonna cause a rerender. So this we'll go ahead
and have that effect. So let's go ahead and go to a component. Let's just type some stuff inside of here. So I'm gonna go ahead and
comment out my previous console logs so that we know
that it's coming from this one. So let's go ahead and
refresh and now we can see, I re-rendered and if I
type in a bunch of times, you can see every single time I type or some kind of rendering happens, it goes ahead and
reflects on the page okay? So this is what is happening here. Now this is how we go ahead and tack into that point in
the component lifecycle. So this allows us to have this
power on every single render. However, this could be quite expensive, we don't always need that. Sometimes we only need to go ahead and render something on the first mount. For example the componentDidMount
method over here. Right the componentDidMount
method over here, we need a way of replacing
that and that is over here. So as you can see over here, this useEffect call, what is the difference
between this one and this one? So this one you can see
has the dependency array inside of it right? But it has nothing inside
the dependency array. And what that tells the React is only run this on the first render right? So only run it when the
component mounts and after that, if there is subsequent
rerenders don't run that code. Right so it's only when
the component mounts right? And it's only when the
component mounts first time. Right so essentially this right here by including this empty
array dependency list will go ahead and replace
this componentDidMount okay? So let's go ahead and see that in action. So I'm gonna go ahead
and say here console log, and we're gonna keep this one
for every single re-render. And here I'm gonna say let's just say the component mounted. Okay? So now if we go ahead and
come back and refresh, it says the component mounted, and obviously that triggers
as a rerender as well. But look what happens guys, if I go ahead and type the I re-rendered should fire off the component mounted should not fire off. So let's go ahead and type in. Perfect. You guys see that? The I rendered gets fired up
with but component mounted did exactly as we expected it. It did not fire off again. So that's perfect and what that will
essentially allow us to do is go ahead and replace this
lovely snippet over here called the componentDidMount. So we don't actually need
this complexity anymore. Now the useEffect can do that right? So really, really nice stuff. Now let's move over to the second bit where we're gonna talk about the componentDidUpdate placement. Okay so the componentDidUpdate previously only got triggered if the
props changed however, we might want a bit more granular sort of control over this aspect right? So what we can do is we
can actually replace this with the useEffect, but this time we go ahead and
we simply include a variable inside of the dependency array. Now this is a array, which means you can include one or as many variables as you want in there at any time any of
those variables changes, it will trigger off this code. Now you can see what we can do is we can include props in here. We can also include the pieces of state. We can include anything that
we wanna go ahead and trigger the rerender for this makes it essentially a
lot clearer because before when we saw componentDidUpdate
it wasn't always clear that our re-render was
about to happen or not. So this makes it essentially
very very clear in knowing when that piece of code
is gonna get triggered. Now a rule of thumb is that imagine we did not go ahead and include
the dependency however, here we wanna say the name changed right? So we only wanna trigger it this off. When the name changed. If I go ahead and save this
and I open up my compiler, you're gonna actually see that it warns us because hang on, you have a dependency in here. Your code is dependent
on the name variable but you haven't included
the name as a dependency inside of that dependency array. So if you go ahead and
check your compiler, it'll actually warn you of this it'll say "React Hook useEffect has
a missing dependency name. "Either include it remove
at the dependency array." Now if we remove it, it's gonna go ahead and
trigger on every re-render, which isn't optimal. So we need to go ahead and Pap in the variable that it's
dependent on so that I hope that makes sense. And imagine we had different ones. Imagine we have another
variable called age for example, then you would also need to
go ahead and include it here. So that way this code
reflects the latest values as it's dependent on these two variables. Okay so whatever variables
you use inside of here, whether it's props, pieces of state, they have to go inside of this right? Now if we go ahead and get rid of the age, because we didn't define a
variable so it would error out. So let's go ahead and do that and you should see a green little compiled successfully
message and that's perfect. Right? So with that said this one over here. So this over here is gonna
be responsible for replacing the componentDidUpdate lifecycle method. And it works perfectly guys. It really, really does. And it makes your code base much simpler because you look at the
useEffect and you know that this code is only gonna get fired off when the name variable changes. Now something to remember you can see here that it also runs on the first render. Okay so every single useEffect always fires on the first render right? So when the component mounts, this is just a rule of thumb. We must understand this. It always will fire at once
when the component loads okay? So even if we go back here and you guys can read
the React docs to make, to understand why that happens, but I can go ahead and refresh and you see the name changed right? And if as soon as I start typing in right? So in this input field at the bottom, I have an example where I'm just essentially
changing the name of variable via a set name and
re-mapping it to the name. So let's go ahead and
change the name input. So here it says enter a name. So if I say Sonny, so as soon as I type in
every single time I type in, it re-triggers that code. You see it says the name
changed our rerender code, which was in the other
useEffect gets triggered off. And also the one that
we just explained now that will get fired off too right? So I hope that makes a lot of sense. And that is where we go
ahead and essentially replace the componentDidUpdate lifecycle method. Now the final example, and this is probably the one that will, may take a few moments
to get your head around is the componentWillUnmount
lifecycle function okay? So how do we replace with a useEffect? Now the useEffect allows
us to have something called a cleanup function okay? So in every single useEffect so let's use this one for an example, what we can do is we can
actually return a function from the useEffector okay and what this will do is it's known as the
cleanup function okay. Now what this means is before
it essentially re-renders, so before imagine I'm typing
into that input field, every single time I type
in it rerenders right? But before it does that it actually quickly unmounts the component so that it can rerender
another one in its place where we see it happen so quick that it looks dynamic in front of us. But what actually, what we can do here is
we can actually go ahead and unmount something so in this case, let's go ahead and demonstrate
before the name changes. Let's go ahead and say we unmounted. So let's go ahead and do this and save. And what we can do is, and this is actually very powerful because there are going to be
cases where for example, you make a connection to a
database and every single time the component rerenders you don't wanna keep
making the connection. Instead you have to do a clean up, you have to disconnect
the current connection and then reconnect or
it would even be better to only do it on the first render. Right so this is where you have
to think about these things, to know which useEffect or
which implementation to use. But let's check this out in action okay. So I'm gonna go ahead and refresh and let's go ahead and say type in Sonny. So look what happens guys. It unmounted, it re-rendered and the name changed. And here if I go ahead
and type in Sonny as such, you can see it happened a bunch of times. The name changed, we unmounted, I re-rendered, the name changed. And then if I go ahead and type in again, it went it said we unmounted it re-rendered
and the name changed. Right so you see what happens here. It has to unmount first then it goes ahead and
updates the name okay? So this is called the cleanup function. Now I've got a really cool example of how we can show you this one. So what we've done here is I've created a little
helper function called const updateWindowWidth okay? Now bear with me for a sec. At the top we've initialized a variable inside of our state
called window width okay? Now what we've done here is essentially set the
initial value with the window in a width property okay? So this will actually just return a value, which tells us how wide the
width of the screen is okay? And what we've done here
is on the first render so obviously here what we're
saying is on the first render, but I'm gonna show you something first. We're gonna say on every single rerender, I wanna add the event listener so that when the user resizes, I update the window width
and this is a function, which simply goes ahead
and sets the window width, to the new window in a width okay? So every single time it will do that. But let's not have a cleanup function and I'll show you what happens okay? So I'm gonna go ahead and
comment this out for now or what we can actually
do at this point is I'll cut this out and I'll show you the sort of implications if you do this without
correctly cleaning up. So what we're gonna see now is this should actually
reflect on the screen. But what we're gonna see now
is if we go ahead and refresh you see here it says the
window width is four six six So if I go ahead and move it around, you can see it's re-rendering
and this is changing value. Okay? So I'll useEffect is working here. It's actually triggering off
to update that window value. However, what we're not seeing here is that every single time
it triggers that rerender, it's adding an event
listener to the resize action with the updateWindowWidth function. Okay? So that's actually quite expensive, although we might not see any harm here and it works perfectly, what we can actually do is we
can run a piece of code inside of our console called get
event listeners for window inside of parentheses. And you can see you look
it has 113 listeners. And if I go ahead and drag
this around a few more times and I run it, it's gonna have another 146 because it re-rendered that
three more times after that. Right and if we do it again you can see like I'm just gonna go crazy now. And then let's go ahead and do it again and we've got another 50 re-renders. So you can see now it's added
another 50 resize listeners. This is not ideal, and it can extremely
impact your performance of your React app okay? So I'm gonna go ahead and
refresh and you can see just to prove to you that
it starts off with one. We do this a bunch of times
and you can see for example, 24 re-renders later we now have 26 inside of our
resize listeners alright, which is not ideal. So there's two ways of fixing this. The first one is with a cleanup function. So let's go ahead and say okay, before you re-render, let's go ahead and return. So the cleanup function. So when the component mounts
this clean up code will run. We're gonna say remove the
event listener that you added with the updateWindowWidth function. So let's go ahead and do that alright? And let's just see what happens now. So if we refresh, we go ahead and see how many
listeners have been attached. Okay remember because it runs
the first time it mounts. So this is why it is able to work. And let's go ahead and
do this a bunch of times. So let's go ahead and move
this around so we can see, okay I've dragged it
around a bunch of times. It says I re-rendered okay? Now let's go ahead and say, get the event listeners and
you can see we only have one. Right? So this is again really, really nice. And it works really, really well okay? Now there are ways, there are things to
consider with this right? Every single time we do this, it's gonna go ahead and
let's just say console.log and let's just say attach listener. Okay? We're gonna attach the
listener at this point. And I'm gonna go ahead and copy this. And here I'm gonna say
detach listener right? So you can see, you might be thinking
problem solved right? But look what is actually
happening here okay? So we attached to the
listener and then here, if we go ahead and check it, it attach that listener right? Perfect. And if I go ahead and re-size the screen, you can see what's happening right? Every single time I do it, although we only have one
resize listener available, which is what we wanted. It's actually doing quite a
lot of work behind the scenes that we don't even notice right? It's attaching, rettaching, attaching, detaching, attaching and so forth so this is not ideal. So what you can do is in
this sort of situation to further optimize your React app you can go ahead delete
this go ahead and actually only run this on the mount right? So remember it depends on your use case but in this case this would
actually work perfectly because we only wanna attach
the event listener once when the component mounts. And then we wanna basically go ahead and just carry on with our day. Right so let's go ahead and save this. And now if I go ahead and check it, refresh it attached to listener. We can see it's only got one resize array and then we can go ahead and do this. And now regardless of the
number of rerenders you can see, our functionality is perfect, but we don't have any
additional resize listeners nor is it attaching and
detaching every time. It only attached once when
the component mounted right? So the example previously
that I showed you with the cleanup function will actually replace
the component unmount. However you can see now that
it's actually a lot clearer to see that we can further optimize this because of the power
that useEffect gives us. And we can actually
remove this piece of code and just implement the
additional on the mount only to make it further optimized okay? So this is extremely, extremely important and it allows us to go ahead and have that fine grain
control over what our app does at different points in its lifecycle okay? So this was a fundamental part
of class based components. And now as the industry is moving
towards functional components, it's really, really important that you actually go ahead and understand how we can mimic this behavior
in functional components with a lot more control
and power behind it okay? Now just a little note to understand, we can have several useEffects. That's the first thing. So yes you can have several useEffects. And also multiple effects
allows us to separate concerns. Right so one effect could be
used for just console logging whenever a re-render occurs. Another effect could be used for attaching that window listener
that we spoke about earlier. And you see every single one has its own little purpose right? Now I would highly recommend that you go ahead and
practice this as sort of power allows us to increase
the complexity of the app without increasing the difficulty
of reading the code base. And it keeps it relatively simple okay? Now once you're done with this, what I want you to do is I want you to go over to your browser. I want you to go over to the React docs and I want you to go ahead and
give the useEffects section a nice quick read okay? Now I make this a habit of every single time that you
finish one of these tutorials you go over to the React docs, and you make sure that you
give this a thorough read because yes we went over
all of the 12 demonstrations however understanding
the core fundamentals as to why these things work, why they're important is
gonna be a lot more important for your future growth as a developer. So here it explains a few examples. It shows you the cleanup effects. It shows you the timings and the sort of ways that you can fire it for example, conditionally an effect
based on in this case, the props.source okay? In this case, it's gonna fire off based
on the source prop changing and so forth right? Now they have some important different notes that you should read, but I would make this a habit that every time we finish
one of these lessons, you come over here, give it a nice quick read
and that way you can solidify what we just went through today okay? So I recommend that you do this exercise, you code this out and you
get everything working and test it for yourself. And yeah guys that's gonna help
you concrete this knowledge and get good with it okay? So that was this lesson and it was a very important
lesson on the useEffect Hooks. In the next lesson, we're actually gonna do
something pretty fun. We're gonna build our very
own custom Hook alright? It's gonna be a used
random joke generator. So it's gonna be a lot of fun. It's gonna make an fetch to an API service and then it's gonna do
some cool stuff with that. So until then guys, I will see you in the next lesson, carry on working hard and I
will see you later Pap fam. Peace. ♪ I know how they love you now ♪ (exciting future bass music)