Search code examples
next.jsnext.js13

Should I use client component or server component?


I have an api endpoint /api/menu.js

I want to get menu from api and when i hover over an item, i want to get submenu now my question is that I am confused between using server or client component and also if the menu and submenu should be loaded together or just the menu and when on hover the submenu. I am using next js 13.5.3 and i am still learning so i am very confused about this

I tried to create a Navbar.js file and use client but i am confused whether its a good or bad practice

"use client";

import React, { useEffect, useState } from "react"; import Link from "next/link";

export default function Navbar() { const [menuData, setMenuData] = useState([]);

useEffect(() => {
    
    async function fetchData() {
        try {
            const response = await fetch(
                `api`
            );

            const data = await response.json();
            setMenuData(data);
        } catch (error) {
            console.error("Error fetching data:", error);
        }
    }

    fetchData();
}, []);

return (
    <>
        <nav>
            <ul>
                {menuData
                    .filter((item) => item.index === "menu")
                    .map((menuItem) => (
                        <Link
                            key={menuItem.sn}
                            href={menuItem.content}
                            className="px-2 py-1 transition-all hover:bg-slate-50 hover:text-stone-900 relative cursor-pointer"
                        >
                            {menuItem.heading}
                        </Link>
                    ))}
            </ul>
        </nav>
    </>
);

}


Solution

  • Do it with the Server Component because, with the server component, you'll be sending zero javascript to the client and you are not doing anything that holds state or changing things like events on click, change, creating context, using context, etc.

    So, your Navbar Server Component would be,

    import Link from "next/link";
        
    export default async function Navbar() {
     const response = await fetch(`....domain.name/api/menu`);
        
     if (!response.ok) {
         console.error("Error fetching menu data");
     }
        
     const menuData = await response.json();
        
     return (
            <>
                <nav>
                    <ul>
                        {menuData
                            .filter((item) => item.index === "menu")
                            .map((menuItem) => (
                                <Link
                                    key={menuItem.sn}
                                    href={menuItem.content}
                                    className="px-2 py-1 transition-all hover:bg-slate-50 hover:text-stone-900 relative cursor-pointer"
                                >
                                    {menuItem.heading}
                                </Link>
                            ))}
                    </ul>
              </nav>
          </>
      )
    }
    

    I would always recommend fetching data on the server component and pass the menuData to a child component. That child component could be a client component or another server component based on what you are doing. For a better visualization, here is a blog from vercel.