So now that we finished this starting page,
let's as a next step work on this community page.
And for that page, it's actually quite straightforward.
I just wanna populate it
with some dummy content.
And therefore attached,
you'll find my finished page.js file
and you can simply replace yours with it.
So replace your community page.js file
with the one you find attached.
Attached you will also find a page.module.css file,
which you should also add next
to the community page.js file
so that the required styles are available.
Now in that page.js file, you then see
that I got a community component function exported there.
And in that component,
I'm just outputting some dummy text
and some images in the end.
So that if you save everything,
the community page should look something like this,
simply outputting some dummy fallback text.
Because of course the main logic
of this overall demo project will be related to the meals.
It's there where we'll fetch data
and add new meals and so on.
And we'll get back to that soon.
That's why here I just provided some dummy content for you.
Now with that community page populated,
there's one thing about the header
or about this navigation specifically
that I'd like to improve.
We currently don't see which page is active.
I am on the community page,
but this link here is not highlighted when I'm on it
and it would be nice if it were highlighted.
And to achieve this, we can go back
to this main header component
where we have this navigation
and edit this link a little bit.
To be precise,
I wanna add a class conditionally to that link
depending on whether the page
to which this link leads is the active page or not.
Now for that, in that main-header.module.css file,
I did prepare a CSS class called active
that can be added to a link
to give it some active styling.
Therefore all we have to do here is find out
whether this should be marked as active or not.
And we can find out whether that's the case or not
by taking a look at the current path name.
So the part after the domain.
For example, for this community link,
the path is /community.
Hence we know that if the path is equal to this path,
this link here should be marked as active.
For the meals page
and the meals related pages,
we know that this link here should be marked as active
if we are on /meals or /mealsshare
or some other nested page.
So if the currently active path starts with /meals.
And therefore we just need
to get hold of the currently active path.
And that thankfully is also quite straightforward to do
because NextJS gives you a use path name hook,
which you can import from next navigation.
And this hook gives you the currently active path.
So the part after the domain.
And with that path available,
we can then set this meals link here to active
if the path which I'm getting from usePathname,
if that path starts with /meals
so that this link here is marked as active,
no matter if we're on the meals page
or some nested page.
That's why I'm using startsWith.
Now if that yields true,
I want to add the active CSS class.
However, not like this,
but since we're using CSS modules,
instead like this.
And otherwise I'll add undefined as a class
so that no class is added.
Well, and now we can repeat that process on the other link
and simply copy that class name code over there.
Here I just want to check
whether the path starts with community
or since we don't have any nested pages here,
if the path is equal to /community.
And then I still want to add the active class
or no class at all.
Now if we do that though,
you'll be greeted by an error
because it turns out
that usePathname also only works in client components.
And that's by the way, a convenient feature of NextJS.
It will tell you if you're using a feature
that doesn't work in server components
in a server component
so that you can then add that use client directive.
So here the fix is to add use client
at the top of this header.
But here's something to keep in mind.
Whilst you can do that
and the error will then go away
and you can now see that the active link is highlighted,
whilst that all works,
you typically wanna add use client
as far down the component tree as possible
so that you really only turn the components
that need to be converted
to client components into client components
so that the majority of your components
can stay server components
and are rendered on the server
so that you don't lose those server component advantages
for most of your components.
And therefore here,
since this header component contains quite a lot of markup
that does not need to be a client component,
I'll take a different approach.
I'll add a new component file,
nav-link.js sounds like a fitting name.
And I'll add a nav-link.module.css file next to it.
And the idea in this JavaScript file
now is to export a component function
that can be called NavLink
that should simply output that NavLink.
So in the main-header.js file,
I'll simply grab this link here and only that.
I'll cut it
and return it here.
Now for that we must import the link component
from next link
and of course we should make NavLink configurable.
So here I want to get the href prop
and I'll use the children prop for the actual text
that's output between the link.
And then here, I'll use children,
and here, I'll use href.
And then here, I'll also use this href prop
when I check whether this is the active link.
Of course, in order for path to be available here,
we now must use the usePathname hook
I just showed you before
so that we can get hold of the path
and we therefore have to convert this
into a client component
by adding use client like this.
But now it's only that component
and therefore only this small piece of markup
that will be rendered on the client side.
We can go back to the main-header.js file now
and get rid of use client here
and get rid of that usePathname import
and get rid of the usePathname usage
because now there we can simply use
that newly added NavLink component.
So I'm importing that
from the NavLink component file
and I'm then outputting it like this.
And you can use client components
inside of server components like this.
We did do that before with the image slideshow.
We're now doing it again here with the NavLink.
Now NavLink then takes the link text here
between those tags.
So in this case, browse meals.
And we must set this href prop here to /meals.
And of course now we can also use that here
for the community.
Here, we now have our foodies community
also turned into a NavLink.
We just have to make sure
that we point to /community.
And with that we made sure
that this main header component is not converted
to a client component
and is therefore still rendered on the server.
And instead only this small part of it
is rendered on the client.
Now of course here I'm now getting an error
that classes is not defined
because in NavLink, I'm referring to the active class,
even though this classes object isn't available here.
And to work around that,
I'll simply add an import here
where I import classes from nav-link.module.css.
Of course at the moment, this is an empty CSS file though,
and therefore we should go
to the main-header.module.css file
and grab the active class here
and add that here in that nav-link.module.css file.
We can actually also grab the link related styles here
and cut those
and also add them here in the nav-link.module file
and change the selector
from an anchor element,
nest it in some element with a nav class
to maybe link,
so to elements that have the link class on them,
like this, here and here.
And with that back in nav-link.js,
we can add that link class to these links
so that we either have link
and the active class added or just link.
And to make that work, I'll convert this here
into a template literal string
into which we can easily inject dynamic values
that will be converted to strings
so that here I have classes.link
and classes.active being set on the link.
And otherwise if the link is not active,
I just add classes.link, like this.
And that's now my adjusted NavLink.
And with that, everything works again,
but now only the NavLinks are also rendered on the client.
All the rest is still only rendered on the server.