Navigation and next/link
In this chapter, we will build a basic navigation to navigate between two pages: the home(page) and a second page
So first, let's create that second page
In the app
folder, create a new blog
folder
Then, inside the blog
folder, create a new page.tsx
with the following content:
Next, we are going to create a component for the main Navigation bar of our app
In the components
folder (that is in the root of the project), create a new header
folder
Then, inside of the header
folder, create a new Navigation.tsx
file and add the following content:
First, we create a typescript interface and then use it to type our static list of pages. Of course, in a more complex project, you might want to fetch this list from a database (at build time), but for our simple example, a json will do, then we iterate through the list to create an entry for each page in our nav
element
The important part here is to use the Route
type (that we imported on top) for the href
value to ensure that next/link understands it is a route and not just a random string, without the Route
type, you will end up seeing errors like this one:
Finally, we open the layout.tsx
that is in the app
folder to import/use the navigation component, like so:
Line 3: we import our new HeaderNavigation component
Line 19: we replace the "my header" placeholder paragraph we had earlier with our new HeaderNavigation component
Line 20: we display the current date & time, which we will use for a test in a bit
Understanding why using regular anchors is NOT recommended
For now our links use a regular HTML anchor element, this is to demonstrate the difference between anchor elements and using next/link (which we will use in the next chapter)
Now save the layout file and launch the dev server if it isn't already running (using the npm run dev
command)
Next, open your browser and go to the project’s homepage at http://localhost:3000/
Then open the developer tools (by pressing the F12
key or right-clicking inside of the page and selecting Inspect
) and make sure the Network Tab is open
Make sure the network tab is empty by clicking on the Clear networking log icon in the top left corner of the developer tools, to clear the networking log:
Then click on the Blog link in the top navigation to go to the second page we just created
Now look at the Network tab logs, and you should see something similar to this:
The most important information is the first row of the logs, if you look at the Type column, you will notice that the Blog page is a document, and in the Method column it will tell you that it was a GET request (I will explain in a bit why we did this initial test)
Now have a look at the time we print on top of the navigation, click on the navigation links, and notice how every time we navigate to a page, the time gets updated, which makes sense as we reload the entire page every time we navigate (we will see in the next chapter how this is different when using next/link)
Using next/link instead of anchor elements
Now let's replace the anchor element (<a>
) we used in our navigation component with next/link
Line 2: we import the Link component from the next/link package
Lines 21 and 27: we replace the HTML anchor element with the Link component
Now we repeat the steps we did in the previous chapter: ensure dev is running, open Chrome, navigate to http://localhost:3000/
, open the developer tools, click on the Network tab, and clear the networking logs
Before you make the second test, make sure you are on the homepage (http://localhost:3000/
) and that the Networking log is cleared
Now click again on the Blog link in the top navigation
Now look at the logs of the Networking tab once again:
Have a look at the first line (actually also the second line because there are now two RSC fetches being made); remember last time when we used the anchor, we had a page request on the first line requesting the entire Blog document, this time we just have two fetch requests getting some RSC (react server component) data from the server; the total of requests is now 2 compared to the previous test where we had a total of 7; this is good because less requests means faster loading times, and less traffic from your server also means reduced hosting costs
Faster loading times are, of course, important because the user will be able to navigate faster, and if an app is fast, the user is happy, but it is also great because your server running Next.js will spend less time working on responses, which means it will be able to handle more requests and finally faster loading times will also improve your SEO score
Finally, look again at the time we print on top of the navigation, and you will notice that this time, it doesn't get updated anymore, this is because our layout does not get re-rendered every time we navigate to a new page, which is because Next.js has only replaced the main section of the page but did not make any changes to the layout (this is why on my blog, in the top header if you hit play; the songs will continue playing even if you visit a new page; 20 years ago to achieve the same thing I had to put the player into an iFrame, but today with Next.js / React this has become effortless)
To be clear, server component layouts DO NOT re-render on navigation but client components (when using the 'use client' directive in a layout) DO re-render
You can now remove the <p>{new Date().toString()}</p>
test (in /app/layout.tsx
at line 20), which we added to demonstrate that the navigation does NOT re-render, we will not need it anymore
Highlight the current route using the next/navigation
Next, we are going to use the pathname of the current page, using the usePathname
hook from next/navigation, then we will check if the first segment of the current path matches one of the entries in our navigation items list, if there is a match we will highlight that anchor element using CSS
Update the Navigation.tsx
like so:
Line 1: we add the use client
directive because we are going to use usePathname, which is a hook that we import at line 3; the component needs to be a client component when you use a hook as described in the Next.js "When to use Server and Client Components?" table; we only convert the component to a client component now because it is recommended to turn as few server components into client components; it is recommended to NOT convert all components to client components, only do so if a component needs to be interactive or requires things like the hook we are about to use
Line 3: we import usePathname
from next/navigation
Line 14: we get the pathname
for the current page
Lines 21 to 38: we have added a function that will check if the pathname starts with the path of one of the items in our navigation, if it does, then we add an active class to the className of that item
Line 48: we use our isActiveCheck
function to check if that item is active, if it is, the function will add a class to className
, else it will leave className
empty
Now launch the dev server if it isn't already running (using the npm run dev
command), then open your browser and go to the project’s homepage at http://localhost:3000/
Then right click into the page and select Inspect
Have a look at the the two links inside of the <nav>
element (inside of the <header>
element), you will see that one of the two now has an .active
class and when you click on the links in the navigation that class will jump from one anchor to the other, depending on what page you are. In the next part of the tutorial we will add styling to make this active class more useful.
Congratulations 🎉 you created your navigation component using next/link and next/navigation
If you liked this post, please consider making a donation ❤️ as it will help me create more content and keep it free for everyone