Open In App

Proper way to use server component inside a client component in Next.js

Last Updated : 16 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Next.js, a popular React framework, helps to build powerful web applications with ease. One of its standout features is the ability to seamlessly integrate server-side logic alongside client-side components. This allows for dynamic content rendering, efficient data fetching, and enhanced user experiences. In this article, we’ll explore how to use server-side components within client-side components in Next.js applications.

Prerequisites

What are Server Components ?

Server components were first introduced in Next.js 13 and are rendered on the server which reduces the amount of JavaScript shipped to the client computer, enhancing the performance of the website. All the components are by default server components and you have to specify ‘use client’ at the of the file to convert it to client rendered component. Server components are better for Search Engine Optimization and there is no initial white screen like normal react components. However, importing a server component inside a client component will be of no use because it will rendered on the client side.

Steps to Initialize a Next.js project

Step 1: To initialize next.js project enter the below command in terminal.

npx create-next-app@latest
Screenshot_20231228_192506

Project initialisation

Step 2: To start the app type in terminal

npm run dev

Step 3: Create components folder and create 2 files ClientComp.tsx and ServerComp.tsx inside the folder. If you are using Linux , then you can do the same by running the command below.

mkdir components && cd $_ && touch {ClientComp,ServerComp}.tsx

Dependencies:

 "dependencies": {
"react": "^18",
"react-dom": "^18",
"next": "14.0.4"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10.0.1",
"postcss": "^8",
"tailwindcss": "^3.3.0",
"eslint": "^8",
"eslint-config-next": "14.0.4"
}

Folder Structure:

Screenshot_20240401_140215

Project structure

Example: Now that we have initialised Next.js project, lets create simple client and server component.

JavaScript
//app/page.tsx

import ClientComp from '@/components/ClientComp'
import React from 'react'

const page = () => {
    return (
        <ClientComp />
    )
}

export default page
JavaScript
//components/ClientComp.tsx

"use client";

import { useState } from "react";
import ServerComp from "./ServerComp";

const ClientComp: React.FC = () => {
    const [state, setState] = useState(0);
    return (
        <div className="w-full h-screen flex 
        justify-center items-center">
            <div className="w-2/3 h-2/3 
            bg-pink-300 flex  flex-col 
            justify-center items-center">
                <p className="text-3xl font-semibold">
                    Client Component</p>

                <p className="mb-5">Rendered on Client side</p>

                <div className="flex gap-3 border border-black
                 rounded-lg p-2 px-5 m-2">
                    <p className="text-2xl font-semibold">
                        Count: {state}</p>

                    <button
                        className="bg-blue-500 hover:bg-blue-700
                         text-white font-bold py-2 px-4 rounded"
                        onClick={() => setState(state + 1)}
                    >
                        Click
                    </button>
                </div>

                <ServerComp />
            </div>
        </div>
    );
};

export default ClientComp;
JavaScript
//components/ServerComp.tsx

const ServerComp = () => {
    console.log("This console log is from the server component.")
    return (
        <div className="w-2/3 h-2/3 bg-blue-300
       flex flex-col justify-center items-center border border-black">
            <h1 className="text-3xl font-bold">Server Component</h1>
            <p className="text-xl">This component is rendered on the server.</p>
        </div>
    )
}

export default ServerComp

Output:

Server Component inside Client Component in Next JS

Server Component in Next JS

Looks good, then what is the issue?

Problem:

Server component is not rendered in server side but is being rendered on client side. You can verify this by going to source tab in chrome developer tools.

Screenshot_20231215_194717

Server component is rendered in client side


In the source tab of debugging tools, we can see ServerComp.tsx file is visible. console.log() statement present in <ServerComp/> is printing in browser console which means the component is rendering in client side. So all the confidential information present in server component now can be seen seen by client and extra unnecessary JavaScript bundle is being shipped to client making the website slow, killing the purpose of using server components.

Solution:

The page component is server side. So if we can import the server component and pass it as a child prop to client component. In this way server and client components are decoupled and it will solve our issue. Place the children where you want to data to be placed. Behind the scene, Next.js is rendering the server component before the rendering of client component.

JavaScript
//components/ClientComp.tsx

"use client"

import { useState } from "react"

const ClientComp: React.FC
    < { children: React.ReactNode } > = ({ children }) => {
    const [state, setState] = useState(0)
    return (
        <div className="w-full h-screen flex 
    justify-center items-center">
            <div className="w-2/3 h-2/3 bg-pink-300
       flex  flex-col justify-center items-center">
                <p className="text-3xl font-semibold">Client Component</p>

                <p className="mb-5">Rendered on Client side</p>
                <div className="flex gap-3 border border-black
          rounded-lg p-2 px-5 m-2">
                    <p className="text-2xl font-semibold">
                        Count: {state}</p>

                    <button className="bg-blue-500 hover:bg-blue-700
             text-white font-bold py-2 px-4 rounded"
                        onClick={() => setState(state + 1)}
                    >
                        Click
                    </button>
                </div>
                {children}
            </div>
        </div>
    )
}

export default ClientComp
JavaScript
//app/page.tsx

import ClientComp from '@/components/ClientComp'
import ServerComp from '@/components/ServerComp'
import React from 'react'

const page = () => {
    return (
        <ClientComp>
            <ServerComp />
        </ClientComp>
    )
}

export default page


Now we are passing server component from page component which is a server component to client component. If you see now see source tab in developer tools, server component will not show and console logs are now appearing as the it is rendering on server side.

Rendering Server Componenr in Next JS

Server component is rendered in serve



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads