We're now using the "useQuery" hook
to fetch and cache the user data.
Now, one advantage of React hooks in general
is that they make it easy to extract reusable logic.
So what I want to do now is extract this bit of code
into a custom hook function.
This way we can move the data fetching logic
outside of the component.
I like to have another folder
at the top-level of the project, called "hooks".
And inside that we can create a new module,
that I'll call "user".
Here we want to create a custom React hook,
that's simply a function whose name starts with "use".
In this case we can call it "useUser",
since it will return the user data.
Now, in that function we simply want to do
the same thing we did in the NavBar,
that is call "useQuery".
But from here we want to return the "query.data",
that is the user value.
Then we need to import any functions we use,
that are "useQuery" and "fetchJson".
And that's it. We wrote a custom hook.
With this, in the NavBar we can remove the old code,
and simply call "useUser" instead,
that will return the "user" object.
We can also remove the "useQuery" import,
since we're no longer using it in this file.
So, this is already better because
we moved all the logic to fetch the data
to its own module,
which means that in this component
we can focus on how to render the data on the page.
But let's test our app and make sure
that we didn't accidentally break something.
It still works fine:
the NavBar shows that we are signed in as Alice.
Now, the other advantage of having a custom hook
is that if we want to access the user data
in some other component we can easily do that now.
For example, if we go to the ProductPage,
let's suppose we want to add that
slightly silly feature I suggested before,
that is display that this is a special price
just for this user.
Now that we have this "useUser" hook
we can simply copy this line,
and go and paste it into the ProductPage,
that is this one.
At the beginning we can call our "useUser" hook
and get the "user" object,
so that, after the price,
we can add another paragraph
saying "Only for" and the "user.name".
And if we save, there it is:
it says "Only for Alice!!!"
Ideally we should check
if the user is authenticated first.
But that doesn't matter, because
this was just a quick example,
and I'll undo these changes now.
But that shows how easy it is now
to get the "user" data in any of our components.
No need to use a state management library
such as Redux or similar.
So, I strongly recommend creating a custom hook
for any piece of data you fetch from an API,
encapsulating the "useQuery" call
with the right data fetching function
and configuration options.