Refactor a Next.js 14 Page to Utilize Both Server and Client-side Rendering

Shadid Haque
InstructorShadid Haque
Share this video with your friends

Social Share Links

Send Tweet

To take advantage of Next.js app router, we need to separate our client components that need state from the rest of the page so we can load data on the server.

To do this we'll refactor the list of rooms into it's own RoomList component which will take the client-side React hooks with it. This way we can load all our rooms on the server and just pass it to RoomList which will start to stream the rooms as we create them.

The final step will be to turn the form for creating rooms into a server action. You'll notice that we will need to instantiate a new fauna client within the server action even though we have a client available in that same page.

[00:00] Here in our page component, we're going to scroll down. So the portion that renders existing rooms, we're gonna turn this into a new client component. I'm going to remove all the JSX. And then I'm going to replace this with the room list component. [00:21] This component has a rooms prop, and we're going to prefetch the rooms data from database in the server side. Let's add the logic to query these rooms from server side. So we're gonna scroll up. And then I'm going to write const room [00:40] response equals to await client dot query, round bracket, f QL backticks, and then room dot all. So it's pretty much the same query that was in our fetch rooms function. Since this is not inside a useEffect, this is going to be server [01:00] rendered by default. We also have to remove the use client from the top. So this component becomes a server component and this function is missing async. So we'll add that as well. Next, we're gonna grab the rooms from the rooms response. So I'm going to check if rooms response dot [01:20] data dot data exist. And if it exists, then we're just going to loop over this array. And for each room, we're going to return the room ID and the name of the room. [01:44] And if room's response doesn't return anything, then we're simply just going to return an empty array. Under components, we'll create a new file called room list dot JS. And let's create the component. I'll write export default function room list. And we're going to return some JSX here. [02:04] We're going to return a simple div. Inside the div, we have a header that says all rooms, and then we're going to loop over all the rooms. And for each room, we're just going to return a link to that room just like how we had it in the other component. [02:34] And we'll also import the link from Next. Js here. Next, we'll pop open the terminal and make sure the application is running. Now if we go back to our browser and in our app, we'll see some errors. And this is perfectly fine because we're refactoring. Now this particular error is trying to tell us that we're trying to [02:54] import user state in a component which is not a client component, and this is coming from source app page dot JS file. So we're gonna go ahead and fix this. Now back in our page component, we'll just remove the imports from React. And let's remove these user states that we don't need. [03:15] And we're gonna remove the user ref as well. Now we also have this fetch rooms function and this useEffect here that we can also move to our room list component. So let's go ahead and do that. So I'm going to cut this code block and paste it back [03:35] in our room list component. And let's turn room list component into a client component. And we're also going to import useEffect and useEffect from React. [03:55] And then de structure the rooms props here that is passed from our page component. And then we're gonna create a state variable called existing rooms, and we will set the initial value of existing rooms to the rooms props. And then we're also going to [04:15] create a stream ref variable using useRef. And then let's import client and FQL from fauna and initialize a new fauna client. Next, we're gonna go to our JSX and [04:35] switch the rooms to existing rooms state variable. And then back in our fetch rooms function, we don't have to do the room dot all query because we're already going to prefetch all the rooms in the server side and pass it to this component. So we can simply get rid of this. [04:58] So back in our browser, we're getting a different error now, and it's saying that we're trying to use client before it is initialized. So let's go ahead and take care of this problem. So we're gonna go back to our page component, and we're going to initialize the font client at the top of our function. [05:20] Now going back to our browser, we see there's another error. And this time it's complaining about the room name state variable. So we don't have this state variable anymore. So we're gonna go back to our page component. And in the form, we're gonna navigate to the input and we're going to delete the [05:40] value and on change handler from this input. Now we can submit this form server site. So I'm going to change on submit in the form element to action, and we don't need the prevent default here anymore. And we change the param name to form data, and we'll add the word use server. That way Next. Js will [05:59] know that this is a server action. And then we're gonna write const room name equals to form data dot get room name. So this room name comes from our input element. So we're gonna give our input element a name, which is gonna be room name. And back in our browser here, and [06:19] I think we forgot to import the room list component in our page component. So let's go ahead and fix that. So in the page component, we're just going to import the room list component. Now looks like we still have one more error. It can't find useRef in our room list component. And again, getting errors like [06:39] this is fine, especially when we're refactoring. So we're gonna go back to our room list component and import useRef from React. Now if we go back to our browser, we will not get any errors. However, if we try to create a new room, we're gonna get this [06:59] error. It can't find the fauna client in the server action. So let's go ahead and fix this. So we'll go back to our page component. We're gonna define the fauna client inside create new room function after the use server keyword. That way the [07:19] server action will have access to it. Let's format the code a little bit. And now we should be able to create a new room.