Next.js Discord

Discord Forum

Cannot export Metadata because Next.Js is saying I'm using "use client" on layout.tsx??

Answered
Little Shearwater posted this in #help-forum
Open in Discord
Little ShearwaterOP
Ecmascript file had an error
  18 | });
  19 |
> 20 | export const metadata: Metadata = {
     |              ^^^^^^^^
  21 |   title: "RblxWork",
  22 |   description:
  23 |     "Test.",

You are attempting to export "metadata" from a component marked with "use client", which is disallowed. Either remove the export, or the "use client" directive. Read more: https://nextjs.org/docs/app/api-reference/directives/use-client


ROOT CAUSE:
- NavigationLabelsList.tsx (Using "use client")
"use client"
import { usePathname } from "next/navigation";
import { NavigationLabel } from "../WebNavigation/NavigationLabel";
import { useMemo } from "react";

export default function NavigationLabelsList() {
    const pathName = usePathname();
    const isHidden = useMemo(() => pathName === "/sign-up" || pathName === "/login", [pathName]);

    return isHidden ? null : (
        <div className="w-auto h-16 flex items-center space-x-10">
            <NavigationLabel href="/about">Why RblxWork</NavigationLabel>
            <NavigationLabel href="/talent">Find Talent</NavigationLabel>
            <NavigationLabel href="/job-listing">Find Work</NavigationLabel>
            <NavigationLabel href="/news">What's new</NavigationLabel>
            <NavigationLabel href="/plan">Pricing</NavigationLabel>
            <NavigationLabel href="/dashboard">Dashboard</NavigationLabel>
        </div>
    )
}


WHERE ERROR OCCURS: (Server Component)
import type { Metadata } from "next";
import localFont from "next/font/local";

import "./globals.css";
import RblxWorkFooter from "@/UI/Components/RootLayout/RblxWorkFooter";
import RblxWorkNavigation from "@/UI/Components/RootLayout/RblxWorkNavigation";

export const avenirRegular = localFont({
  src: "./Fonts/AvenirLTStd-Medium.woff2",
  weight: "400", // Regular weight
  display: "swap",
});

export const avenirBold = localFont({
  src: "./Fonts/AvenirLTStd-Heavy.woff2",
  weight: "700", // Bold weight
  display: "swap",
});

export const metadata: Metadata = {
  title: "RblxWork",
  description:
    "Test",
  icons: "/Website Resources/Favicon/logo.ico",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body className={`${avenirRegular.className} antialiased`}>
          <RblxWorkNavigation />
          {children}
          <RblxWorkFooter />
      </body>
    </html>
  );
}
Answered by Little Shearwater
## SOLUTION!!!!

I've finally fixed this issue by moving the exporting fonts outside the server component and made it global and can work with client/server.
View full answer

49 Replies

Little ShearwaterOP
This is SOOOO ODD 😭
The problem is FIXED when you:
1. Remove the export metadata

OR

2. Remove the "use client" BUT also remove all client interactivity (not what I WANTED)
So I thought: Can server component contain client components, I looked it up and it seems that they can, so I'm CONFUSED!!!!
Red-faced Cormorant
your error is due to you having "use effect" at the top instead of "use client", any hook starting with the word "use" requires "use client" directive
I meant to say "use client"
And usually it occurs when you try to use the directive "use client", I am not sure why. It's so weird.
Little ShearwaterOP
Just updated the error since I realized it was wrong error lol
to be clear: when you remove "use client" in the client component, it gets fixed (along with removing effects)
that's something I don't want to do
Red-faced Cormorant
You need to use "use client" direct in a component that uses hooks, unless its already being called somewhere that is already a client component.
Dwarf Hotot
You cannot set metadata in the same page of use client because metadata only set in server component. So to set metadata create server component add metadata and then call client component in the server component
@Red-faced Cormorant your error is due to you having "use effect" at the top instead of "use client", any hook starting with the word "use" requires "use client" directive
Not every, useId()does not require it, neither does use(). (Yes, use()is considered a hook by the React team and it's in their docs as such). The rest of hooks do need the "use client" directive.
@Little Shearwater to be clear: when you remove "use client" in the client component, it gets fixed (along with removing effects)
If you remove "use client" that is no longer a Client Component, that's why you need to remove the hooks that require it.

What "use client" directive does is telling the Next.js bundler "send this chunk of code and everything that is owned by this file to the browser".

Next.js treats all components as Server components by default, which means you need to opt out of that in case you need to use client-only features like React State, LifeCycle methods (mount, unmount, etc.), the window object and client-only APIs. Only in these situations you should be tempted to write "use client" at the top of the file, and you should try to do it only on very specific components, not the whole page.
So now you have to make a choice depending on your needs:
a) Do you need stateless logic and markup or make use of the server to fetch data or set up metadata (... and more)? => Server Components (default)
b) Do you need interactivity, broswer APIs, State and synchronizing your component to external sources? => Client Components (the *typical *way of writing React)

My recommendations: stick to server components until you need client side features, then make a new file marked with "use client" and create your client component, then you can use these *client *components anywhere in your React tree.
Little ShearwaterOP
Yep I understood what 'use client" is used for, but I mean that:

1. Layout.tsx is already a server component, that's the pretty much the root layout that share all UIs (which also export metadata).

2. NavigationLabelsList.tsx is a part of children in layout.tsx which uses "use client" to use hooks (to get path name, etc etc). So of course I need client interactivity.

Imagine the structure of my project:

Layout.tsx (SERVER COMPONENT)
- RblxWorkNavigation.tsx (SERVER COMPONENT)
-> RblxWorkNavigation.tsx also calls the client component (NavigationLabelsList.tsx)
-> NavigationLabelsList.tsx uses "use client" and try to import hooks

and then that's how the error occurred
I was talking about issues with server componenet containing nested component children that might be both client and server.
So I thought Layout.tsx cannot contain children that is client component? They all must be server-component only?
@Dwarf Hotot You cannot set metadata in the same page of use client because metadata only set in server component. So to set metadata create server component add metadata and then call client component in the server component
Little ShearwaterOP
I guess the server component (Layout.tsx) has children that later calls the client component to use hooks, etc etc in the same page. Isn't that the issue?

FYI: I made sure that Layout.tsx is the ONLY server component that set metadata.
I understood the difference between Client Components and Server Components, what I am the most confused about is: It does not work the way I expected to be.
@Little Shearwater Just updated the error since I realized it was wrong error lol
Ruby-throated Hummingbird
you can't use meta data on a client side
@Ruby-throated Hummingbird you can't use meta data on a client side
Little ShearwaterOP
No you don't understand, I am not using "use client" on the layout, it is the server component
the only client component is NavigationLabelsList which is far away from Layout.tsx (root)
I am not sure how that only client component can cause issues with metadata (which is done on Layout.tsx)
NavigationLabelsList doesn't create or export metadata, only Layout.tsx
and it has nested children (which is where NavigationLabelsList.tsx is from)
and somehow this happened 🤷
So I am even thinking this is a bug.
because it doesn't work the way client components & server components worked
Ruby-throated Hummingbird
oooh i see it now
Little ShearwaterOP
yes!
🙏
If I remove the only client component, the issue is gone, or I make NavigationLabelsList a server component and remove some effects, the issue is gone.
So it's like as if the NextJS is telling me "Your root server component cannot contain a mix of nested client components & server components" 😭
The version of NextJS is: v15.1.6
Little ShearwaterOP
## UPDATE!

It seems that this tiny line is causing the error lol

import { avenirRegular } from "@/app/layout";
import Link from "next/link";

interface NavigationLabelProps {
    children: string
    href: string
}

export function NavigationLabel(props: NavigationLabelProps) {
    return (
        // HERE HERE HERE
        <Link className={`${avenirRegular.className}`} href={props.href}>{ props.children }</Link>
    )
}


This is the sub-componet that is used by NavigationLabelsList.
I don't understand HOW Link component can cause this error
It looks like making it server-component fixes the issue.
by using "use server"
Nevermind, this causes fetching waterfall.
Little ShearwaterOP
Looking even DEEPER into this thing and it seems that removing classname finally removes the problem:
<Link className={``}/> // Removed the classname
You might ask where the avenirRegular is coming from. Well it looks like it's coming from layout.tsx which is a server component.
So in other word: The client component is trying to import something from server component (layout.tsx)?
Is that allowed and is supposed to happen?
These on Layout.tsx
export const avenirRegular = localFont({
  src: "./Fonts/AvenirLTStd-Medium.woff2",
  weight: "400", // Regular weight
  display: "swap",
});

export const avenirBold = localFont({
  src: "./Fonts/AvenirLTStd-Heavy.woff2",
  weight: "700", // Bold weight
  display: "swap",
});

export const metadata: Metadata = {
  title: "RblxWork",
  description:
    "Test",
  icons: "/Website Resources/Favicon/logo.ico",
};
Little ShearwaterOP
## SOLUTION!!!!

I've finally fixed this issue by moving the exporting fonts outside the server component and made it global and can work with client/server.
Answer
Little ShearwaterOP
It looks like anything exported from server component becomes server-thing only.
I guess that's it for now.
Sadly I've not been able to receive helps from you guys but at least I resolved it.