
Build a Fullstack App with Next.js, v2 SidebarLink Component
A second and third version of this course released using Next 13+, but this course is great if you want to see another example fullstack project. We now recommend you take the Build an AI-Powered Fullstack Next.js App, v3 course.
Transcript from the "SidebarLink Component" Lesson
[00:00:00]
>> Now we need to work on the sidebar component which is basically just gonna be literally the sidebar on the left of the dashboard. So, we can work on that and this one's pretty simple, it doesn't really do anything crazy, although it is going to probably introduce our first client component.
[00:00:22] And that's because in the sidebar, we wanna be able to highlight the icon of the route that we're currently on, the active route. And we only have access to what route we are on on the client, so that component that's been highlighted, the icon opponent, wherever we call it, needs to be a client component, because we can't do it on the server, we don't have access to it.
[00:00:45] The hook that we use to access the current route, you can't use the hook on the server, so, and there's no window doubt location on the server, so there's really, not a good way to get it. I mean, I guess you could hack it on the server, you could look at the request object maybe and try to figure it out from there, or the headers or something like that.
[00:01:04] But that sounds like a lot of work, so probably won't do that. One thing I noticed though, before we move on, as I was going through, I don't actually think our telephone is hooked up properly. I think something's weird going on here. I might not have post CSS included.
[00:01:24] I thought I did, let's see. That might be it. It literally won't work without post CSS so that probably is it, so I'm gonna add that. Come here. Give me just that part. Okay, they really didn't want me to copy that. So, going to NPM install, postcss, which is the thing that's powering Tailwind.
[00:01:57] It literally won't work without that, I thought that was already installed. And auto prefixer just puts the WebKit browser prefixers and all the other prefixers on it for us. And just means dev dependency. Cool. I'm going to run the recommended command that they have for MPX, tailwind CSS init dash P.
[00:02:21] And so I'm gonna do let's see what that yields. I think because we needed a postcss config, I think that even if it's empty, I still think you need that config. Because there's literally nothing in it. But I think it has to be there. So run that again.
[00:02:44] Yeah, that was it. You literally have to have an empty config. Like who, like what about using the config file at the config but there it is, cool. That looks about what I imagined it to look like. So I was able to just get that working by just running MPX tailwind css one word and knit dash p.
[00:03:12] To initialize that config it detected that we already had a tailwind config so it didn't touch that Instead created a postcss config for us which we needed even though it's empty. And we have no configuration. And that's what will break your app. Okay, so it looks a lot better.
[00:03:33] So what we wanna do now is working on that sidebar which we'll go into if we go to home here. Or I don't have anything at home do I? Let's see. I have something at home here I just stopped the server I think come on MPM run dev.
[00:04:02] So if we go to home here, it's going to be the thing on the side here, the little sidebar that we had. That's the sidebar. It's literally in the name. It's a sidebar. So we'll do that. Let's do it. So components. Sidebar tsx. I forgot our notes. Actually what we're gonna do, we're gonna do the other one, the one that's a client component first.
[00:04:36] So this one's actually going to be called the side bar link tsx. Let's do that will first, be a lot easier to follow. This is the actual link that's gonna be in the sidebar. It's like an icon component. So we'll do that and it's actually just probably on the next page of the docs here.
[00:04:55] Yeah, there we go. So this one is gonna be a client component so I'm gonna put use client at the top. And I'm gonna import the link component from Next.js like that And a couple icons from react feather, so we have settings, user, grid, and calendar from react feather.
[00:05:37] It's an icon library. It looks like this. It's actually nothing to do with React, but it's just like the React version of it that points to feather icons, which are really cool-looking icons. I've always used react icons which is really cool lib but I was like I want to switch it up so I'll use react feather.
[00:05:57] I think I like it better than react icons. But anyway, got that and then we want to, it's for this import. This one import right here is the only reason why we have to do use client Use path name. That only works in the client. And the reason I know that, other than the documentation telling me that is, it's a hook.
[00:06:31] Hooks only work on client components, and it's based off of browser api, which only exists in the client component. But i if you're in doubt, you can go to the documentation if you type in use path name, you can see right here. Use pathway and hooks allows you to read the current url path name from a client component.
[00:06:53] They put an underline on it just to emphasize to you this is a client component only hood. Okay, so that's all we have use client here. And then clsx, cool. So next thing I want to do is just, pretty much the strategy is to this sidebar link. If given a link object, it's just going to render out a next link that wraps an icon that has some classes on it.
[00:07:30] That's it and it maps an icon name to an icon. And this is actually interesting. Well, I have to do this and I'll explain it in a minute. It has something to do with the network boundary. And what can be serialized and what can't be serialized. And why you can only pass certain things as client components versus passing them as server components.
[00:07:51] Cuz in reactors this would actually work, but we can't do it here. So I'm just gonna leave my map of icons here, and I'm just gonna give them their names. Literally, the same names that you import as, so settings, user, grid, calendar and you'll see why I'm doing that in a minute.
[00:08:09] And then we'll just make the components so sidebar link On a wise don't I didn't want to, al lright, got a CyberLink here. It's going to take a link object from someplace. And then we wanna get the path name here. So we can say const path = pathname = usePathName like that.
[00:08:43] And then we can say if path. Name triple equals link dot what might have called it, link. Yeah, link. Then this is an active link. So we can just make a let here is active so it's a false. If that's true then because it is active true. You might be thinking, should I put that in the state somewhere so it keep track of it?
[00:09:16] No, it's totally fine. I don't need to keep track of it because it's not gonna change based off an interaction where I need to force a reminder. It's only ever gonna change when the path changes. And when the path changes this thing reloads anyway, it's a client component so I don't need to put this in a state I can just compute it every time I re renders it's free.
[00:09:35] When I say free I mean react doesn't have to compare this, we get it for free because the url changes Okay. Then we wanna get the icon capitalizing it because it's gonna be a component. If you don't use capital letters and react for components, it'll freak out at you.
[00:09:55] So you have these capital letters icons is going to be from icons. Wherever the link dot i, okay, Link dot icon is. So the reason we have to do this, this being a client component, it's going to be rendered in a server component or if we just forget about server components or cli commands right now, these are just two components.
[00:10:25] You can pass another component down as a prop. Like it's totally fine. You could pass a function as a prop. You can pass pretty much wherever you want as a prop to another component, unless it's a server component passing down to a client component. Because there's a network barrier there.
[00:10:41] There is what's happening is the serialization process is happening because it has to cross the network and you cannot serialize a function, which is what a component is. A component's just a function. You also can't serialize like date objects and things like that, or anything recursive. You just can't serialize it.
[00:11:01] So because of that we actually can't pass the icon component itself instead we've got to pass a string that tells us what icon to use and then we can map to it when we're in the component side and that's why we're doing it this way so it does change how he write code just a little bit.
[00:11:19] Because if both of, if everything was client, we wouldn't have to do this mapping here. The link object itself would already know what component to render or what icon to render. Does that make sense? It's a little complicated. It's hard to think about, but because they're gonna be next to each other.
[00:11:39] We're gonna be using a client component and a server component, but they're happening at two different times. And across, one's happening on the server, the other one's happening after the network request was made. So we can't just pass things down like that Okay, let's do this. So let's return our link component like that.
[00:12:00] It's going to have an href of Link dot link. And we're just going to put an icon I got a class size of 40. So to say, wherever the icon was. I think it's a self closing, actually. Here we go. Size of 40 and we got a class name here, gonna use clsx, like so and we'll just grab these really cool Tailwind styles, like that.
[00:12:49] And then className are actually yeah we got to the is active stuff. So if is active and we just wanna go ahead and just add a stroke to it because these icons are SVG so let's add a stroke. Cool. Any questions on that? On why this is a client component, how it's a client component, the network boundary, serialization.
[00:13:32] Anybody ever try to JSON stringify something recursive? Yeah
>> Could you go over the icon thing one more time, please?
>> Yes, I could totally go over the icon thing one more time. So In a perfect scenario, this link object that's getting passed as a prop would already have the icon associated with it.
[00:13:56] It'll be something like this, you probably would have it like that like Link dot icon like it already would know We can't do that with this because this client component is gonna be rendered in a server component and that server component can't pass non serializable props to a client component.
[00:14:18] And a component like link.icon is a function and functions aren't serializable. It cannot cross the network. You can't send a function across the network. You can only send JSON or HTML or CSS, cuz you can't send a function. So therefore we cannot send If a component as a property from a server component to a client upon it, it just won't work.
[00:14:48] Because it won't cross the network barrier just like the date object can't be sterilized. Just like a recursive object can't be sterilized, a function too can't be sterilized. You kind of have to think about it as in like you have to you have to abstract away how react made it so easy for you to, like, have these components live next to each other and think about, like, if you have a server component and you have a client component.
[00:15:14] In between those components is just big red line. That red line is the network barrier, it's the boundaries, it's where the network call happens. If you wanna cross that, you got to be serializable and a component isn't. So it can't cross it though it's not allowed. So that's the way I think about it in my head when I think about seeds it's a big red line there and you can't get past it.
[00:15:41] So yeah so in that case we instead are sending back a stream that map's to an object of icons that are already in the client component so we can scrap it that way because strings are serializable.