Transcript
00:00 Our applications are messy. They have a lot of integration points. We can't just make the entire computer be React components. Well, I mean, maybe you could. React is pretty powerful that way, and composition is magic, but inside of those React components, it's got to integrate with the
00:18 system APIs and maybe third-party libraries and stuff like that. And so, we have side effects that need to happen as a result of changes in our application. And with useEffects, that's how you accomplish this. So useEffect is another hook that you call inside your component,
00:36 which accepts a callback function. You do your side effect thing right here, and then you return a function for cleaning up the mess that you made as part of your side effect here. And this callback function will be called any time one of these dependencies changes, in addition
00:54 to the initial time. So the function gets called, your useEffect will get called, and you'll return your cleanup, and then if any of the dependencies change, this second argument, this array of dependencies, if any of those change, then React will call the
01:12 cleanup function, and then it will call this callback again, like re-initializing things or subscribing to the third party service or whatever it is that you're doing, and then you'll return a new cleanup function to clean that up. So if you're thinking about working with geolocation,
01:30 as your location changes, maybe you need to subscribe to a chat room that's geolocated close to you or something like that. That seems like an interesting app idea. And so your location changes, that is going to change maybe the dependencies. You have your latitude and longitude as your dependencies,
01:48 and so this useEffect is going to say, okay, my cleanup is to unsubscribe from the chat room that I was in before, and then we're going to subscribe to the new chat room that I'm in now, and so now we're getting updated WebSocket events for that new chat room, something like that, as an example. So that's
02:06 the idea behind useEffect. It's just a mechanism for synchronizing the world, the external world, with your internal React application, and performing those types of side effects. It can be a little bit trickier of a hook. There's this thing inside of React
02:24 called strict mode that allows you to help you catch bugs during development, and one of the things that it does is it will actually call your useEffect callback twice. It will call the callback, then it will call the cleanup, then it will call the callback again. And this will catch problems
02:42 of lack of item potency and stuff in your component. Frankly, it's pretty annoying. I don't really like it. But it can help avoid bugs, and so I bring that up because you might observe that as you're working in various code bases, and that's what's going on.
03:00 Just in development mode, React is just helping to make sure that your useEffect is handling not only initialization, but also cleanup and reinitialization properly. And if you're doing that, then you should be in a good place. Another thing to watch out for is if this doSomething makes a state change that's going to
03:18 impact one of these dependencies, then you could end up in an infinite loop. So the dependency changes, so React calls it again, you change the dependency, and so the dependency changes, so React is going to call it again. It just keeps on going forever. More often than not, that happens as some result of an asynchronous
03:36 thing that happens. So you make a fetch request, then it comes back, and you set some state, and then that updates the state that changes the useEffect, and then you make the request again, and you're like DDoSing yourself. It's not a fun experience for sure. So useEffect is one of those
03:54 things that I find myself using less and less over time because there are so many great libraries that are built on top of useEffect that have that dialed in really nicely. And then also, React is continuing to come out with really great alternatives
04:12 to using useEffect for synchronizing things, and we'll look into some of those in the advanced workshop. So that's the idea behind what's going on with useEffect. Something that can be really helpful when we start talking about useEffect is this hook flow chart that Donovan put together a couple of years ago, and it's still very relevant today.
04:30 So it's the React hook flow diagram, and it shows the three phases of a component. So you've got the mount phase, this is the initial render of our component. Then the update, any time you call a state updater, and then unmount when that component gets removed from the page because maybe the user
04:48 navigated to a different page, or maybe they closed the pop open or the pop over menu or whatever it is. So there are plenty of reasons why a component that was rendered before is no longer rendered. That's the unmount phase. So during our initial render, the mount phase, React
05:06 is going to call those lazy initializer functions, so the function that you pass to useState if you're passing a function that is called a lazy initializer. So it's going to call that function, and then it's going to finish running the rest of your component, so creating those React elements. React is going
05:24 to create the DOM nodes for that and set those in the UI, and right after that is done, it's going to run what are called layout effects. We'll learn more about layout effects in our advanced React hooks or advanced React APIs workshop, but they're a special type of
05:42 effect that runs before the browser paints the screen. So in our case right now, React is going to set the DOM, initialize that DOM based off of the UI that we created, and then the browser will update the screen. So there's a time and place between when DOM gets updated
06:00 and the browser updates the screen so that the user can see those updates, and that time and place is important for the layout effects that we'll talk about later. So once the browser paints the screen, updates that UI that the user is looking at, then it's going to run your effect
06:18 callback right here. So there you go, and you're going to return your cleanup function, and then React is going to get these dependencies and say, okay, I will update or recall this callback whenever these dependencies change. Okay, so let's say we do a state update, maybe a state update that changes one of these dependencies,
06:36 and so like, let's say it's the latitude and longitude example. So this is lat, this is long, and then we're subscribing to something here. We updated the latitude and longitude, we're going to recall this useEffect. So first React is going to render, so maybe you display their latitude and longitude in the UI, so React
06:54 will re-render so we get that display updated. React will update the DOM. The cleanup for layout effects and rerunning of layout effects will happen. That's external to what we're doing today. The browser will update the screen, so now the latitude and longitude is something the user can see. And then React will call this,
07:12 and so it will actually call the cleanups first. So we're going to unsubscribe from the old chat room, and then it'll run the effects, we'll subscribe to the new chat room, and then return a new function that will unsubscribe from our new chat room when we're ready to do that. And then let's say that the user navigates to a different page,
07:30 they no longer need to be on this page anymore, so we're going to unmount. So here we're not going to be calling the function again, we don't need the React elements anymore, they're not going to be displayed at all. We just need to clean up the side effects that we put together, and so we're unsubscribing from that chat room now. So we don't have to worry about those
07:48 WebSocket events coming in and nobody listening for them. So that's the basic flow of how all this stuff works together. It's kind of interesting, and hopefully that helps give you a better sense for how all of this stuff works together. One other thing that I'll mention, and then I'll let you get started on this exercise, is
08:06 you can have as many use effects as you like. And so it's best to have use effects that are kind of cover as much as they can. I like to put as much, well we're talking about just use cases, so this use effect covers this use case. I want to put as much of the code inside of that use
08:24 effect as I possibly can. I don't like to actually have these functions that are external to the use effect, because you end up having to worry about, well where are the dependencies? Like what does this thing depend on? What does that thing depend on? You've got to include those interdependencies, because if the things that this depends
08:42 on changes, but we don't recall the use effect, then we're going to be calling a version of this callback that is old or something. So for that reason I like to just put as much as I can inside the use effect. If I'm going to have a use effect, everything that use effect needs should be inside that use
09:00 effect. But then you can have multiple use effects that cover different use cases. So maybe we have one that's subscribing to geolocation changing, and then maybe that's for some use case. And then we've got another one that is handling subscribing to the WebSocket or something like that. And perhaps those could be combined.
09:18 It all kind of depends, and typically with this sort of thing, I like to try both and choose the one that I hate the least. And that's how I live my life. That's my modus operandi. So for this exercise, what we're going to be working on is continuing on this blog search
09:36 UI a little bit to make the user experience a little bit better. Because you will notice that while we can initialize to a specific query, that query does not stay updated. So this is some external state or some external, yeah, state of the world
09:54 that's outside of our React application. We need to keep these things in sync. And I'll just remind you again that this is not typically something that you will have to do in an application because you'll have a router that has a hook that does this, but we're kind of building a simple version of that hook to explore some of these APIs
10:12 that you're definitely going to be using in your app. So let's get started on this exercise.