‫As our first custom hook,
‫let's start with a hook called useMovies.
‫So there are basically two strategies to decide
‫if we want to create a new custom hook.
‫So the first one
‫is that we want to reuse some part of our non-visual logic,
‫so just as we learned in the previous lecture.
‫And the second factor might be
‫that we simply want to extract a huge part of our component
‫out into some custom hook.
‫And so that's actually what we will do in this lecture.
‫So we will take this useEffect here,
‫which fetches our movie data,
‫and we will extract it into a hook called useMovies.
‫And so then we get rid of all of this code
‫here in our component.
‫And of course, if we wanted,
‫we could then later reuse this hook in some other project.
‫Okay, so in this lecture,
‫I will show you how we can extract all the stateful logic
‫that belongs together
‫into a nice and well-packaged custom hook.
‫So let's do that.
‫And actually for that,
‫I will create a brand new file here in our source,
‫and I'll then call it useMovies.js.
‫Okay, and from here, we will export a function,
‫which is going to be our custom hook
‫called exactly useMovies.
‫Okay, and notice that here,
‫I'm not doing an export default, but a named export.
‫And so that's kind of a strategy that I like to use,
‫so using default exports for components like this one here
‫and using named exports for custom hooks.
‫Now, that's not really mandatory,
‫but that's just the way I like to do it.
‫So you could, of course, also do a default export here.
‫Okay, and so let's start
‫by extracting these useEffect here,
‫so this huge thing,
‫and then we will notice
‫that we will need a lot more stuff than just this
‫here in this function.
‫Okay, so give it a save, and immediately,
‫we see that we are missing all of these state variables.
‫So in this case, these state setError functions.
‫And so that's because fetching the movies
‫requires a lot more than just this effect.
‫So notice how we actually also need
‫multiple state variables.
‫So the movies, isLoading, and error,
‫all of them are necessary
‫to make the functionality of fetching movies work.
‫And so, let's also extract them from here
‫and paste them where they're unnecessary.
‫Okay, and then we just have some problems with importing,
‫so import useState
‫and useEffect from React.
‫Okay, so that's looking already better,
‫but we still have some missing information right here.
‫So we're missing the key and we're missing the query.
‫So to fix that, we can simply accept the query here,
‫for example, as a parameter to our function.
‫And so now, remember that this really is a function.
‫This is not a component.
‫And so here, we don't accept props,
‫but really we accept arguments like this.
‫So even though our custom hook is not yet going to work,
‫let's already call it, so useMovies.
‫And so then again,
‫VS Code will automatically import this for us.
‫So now you have this line of code here
‫which again imports the custom hook that we just created.
‫And notice how it's using here at a curly braces,
‫meaning that this is a named export at a named import.
‫But anyway, now here we are calling our new custom hook.
‫And so let's pass the query in.
‫All right,
‫now we're not saving anything to a variable here just yet,
‫because for now, our custom hook is not returning anything.
‫And so let's actually change that.
‫So what exactly should we actually return
‫from this custom hook?
‫Well, basically, we want to return everything
‫that we need here in the app.
‫So basically,
‫all the variables that somewhere in our JSX are necessary.
‫And so that's basically exactly the three pieces of state
‫that we just removed from here.
‫So it's the movies, the error, and the isLoading state,
‫because again, we will need these somewhere here in our JSX.
‫So we have movies, we have isLoading, and we have error.
‫And so again, we, of course,
‫now need access to these variables right here as well.
‫And so that's basically what we will want
‫this custom hook to return.
‫And so, let's return them from here.
‫So I think that's the correct place, yeah.
‫So right after the useEffect, we will return,
‫and we will place them all into one object.
‫So it could be an array as well,
‫but it's very common to just return an object
‫especially when we have so many different things,
‫like movies, isLoading, and error.
‫All right, now here we actually have a problem now
‫with this handleCloseMovie.
‫So let's comment this out for now.
‫And now there's only one thing that we are missing here,
‫which is this key.
‫And so let's grab this, so copying it
‫and then pasting that here as well.
‫So it could also have passed this in
‫as an argument into the function,
‫but I think that the key itself
‫really should be part of this file here,
‫because it is tightly coupled also to the movie URL.
‫And so if we passed in the key,
‫then we should probably also pass in the URL,
‫but that we don't want.
‫So we want to make this as reusable as possible.
‫Okay, and so now, all we have to do is to then, here,
‫basically get the data that is returned
‫and destructure them here into their own variables again,
‫so that's movies, isLoading, and error.
‫And so that's actually it.
‫So again,
‫here we are returning these three pieces of information,
‫so these state variables
‫that we are going to need outside of this custom hook.
‫And so, basically, then this returns an object,
‫which we then immediately destructure right here.
‫And so then,
‫as far as the app component here is concerned,
‫having this is exactly the same as having all the code
‫that we had here in the component before.
‫And so if we give this a save and try this now,
‫then you see that it's working just like before.
‫The only difference right now
‫is that when we select a movie here
‫and then we search for another one, let's say test,
‫then this one here is not closed.
‫And so that's because we are no longer calling
‫handleCloseMovie.
‫So what should we do about it?
‫Well, we can just leave it as it is right now,
‫so in order to make this really reusable,
‫or we could also accept a callback function
‫that the user of this custom hook can pass in if they want,
‫and then we can call that at the very beginning.
‫And so this is a way of customizing this custom hook
‫a little bit more.
‫So we can think of this argument here,
‫again, a bit like the public API of this custom hook,
‫so just like we can think of props
‫as the custom API of a component.
‫So a custom hook like this can also be created by someone
‫and then consumed by someone else.
‫And so that's the whole point of creating reusable pieces
‫of stateful logic, okay?
‫And so, well, let's remove that from here.
‫And just to make this a bit more clear,
‫we can call this at the very beginning of our effect.
‫So we can say callback,
‫and then we only want to call it if it actually exists.
‫And so we can basically do optional chaining
‫on calling a function as well.
‫So that's just like this,
‫or actually the other way around, so like this.
‫And so now this function will only be called
‫if it actually exists.
‫So without this optional training part here,
‫we would first have to check if it does exist,
‫and then we would call it.
‫So if we now try this again,
‫since we didn't pass in any callback yet,
‫this will then work without problems.
‫So you see no problems there.
‫But now we can actually pass in that callback,
‫which is handleCloseMovie,
‫and we can use this function here
‫before it is actually defined.
‫Because remember, that in JavaScript,
‫function declarations like this are hoisted.
‫And so that's one of the big reasons
‫why I don't like to do this,
‫what many people do these days,
‫so writing an arrow function like this.
‫So if I did this, then I couldn't do it like this.
‫I would first have to create a function,
‫but like this, that's not necessary,
‫and so, one of the reasons
‫why I always prefer function declarations.
‫Okay, let's try this again.
‫So let's open some movie,
‫and beautiful!
‫So now the currently open movie is immediately closed
‫as the search query here changes.
‫Great, so with this,
‫we really cleaned up our app component here.
‫So we only have this small effect here left,
‫but we will actually also take care of that in the future.
‫And now let's just quickly recap what we did here.
‫So basically, we took all the logic that belongs together
‫to search for movies
‫and simply placed it here into this custom hook.
‫And notice that we used four hooks to achieve that result,
‫so one useEffect and three useStates.
‫And that's important, because remember,
‫a custom hook actually needs to use at least one React hook,
‫otherwise, it's just irregular function, right?
‫So we took all the logic that belongs together,
‫packed it here into this one function,
‫and then returned everything that is necessary for the app
‫to keep working in exactly the same way as before.
‫Now here we just need to probably also add the callback
‫to the dependency array.
‫But then you see we have this infinite reload here of error.
‫Now, fixing this is too difficult for us at this point.
‫So I actually didn't think of this,
‫because I hadn't even prepared this lecture here before.
‫So let's actually go back,
‫remove that from the dependency array.
‫But since we should really not lie
‫about our dependencies in the array,
‫let's then remove the entire ability to do this.
‫So I will just comment this out,
‫take away the callback, and here as well.
‫So then the custom hook will not work
‫exactly the way as it did before,
‫but that's not a big deal here.
‫So we are just learning,
‫so we just wanted to learn
‫how we can extract this non-visual logic into a custom hook
‫like we just did.
‫And to practice this a little bit more,
‫we will do a few more in the next few lectures.