Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to change the title with metadata when using 'use client' in Next.js

I have a /demo route in my Next.js 13 application, and it is using the App Router. But I am unable to change the title of the page (the current title I am getting is localhost:3000/demo).

I have the following code.

/demo/page.js:

'use client'

 ....

export const metadata = {
  title: 'Demo - ModalJS',
};

export default Demo(){
 return ...
}

The 'use client' is creating the problem, because when I remove it Title changes, but the problem is that I cannot remove it because this component uses onClick which gives an error without ''use client`'

The code inside Demo is as follows:

export default function Demo() {
    

    const [title, setTitle] = useState("Title of your modal");
    const [desc, setDesc] = useState("You description goes here");
    const [theme, setTheme] = useState("light");

    const handleclick = ()=>{
        const modal = new ModalJS( ... stuff related to this library)
        
        modal.show()       //trigger this when you want to show modal
    }


    return <section id={styles.demosection}>
        <div className={styles.demotitle}>Demo</div>
        <div className={styles.form}>
            <label htmlFor="title" className={styles.label}>Title:</label> <br />
            <input type="text" name="title" id={styles.title} className={styles.input} value={title} onChange={(e)=>setTitle(e.target.value)}/>
<br /><br />
            <label htmlFor="desc" className={styles.label}>Description:</label> <br />
            <input type="text" name="desc" id={styles.desc} className={styles.input} value={desc} onChange={(e)=>setDesc(e.target.value)}/>
<br /><br />
            <label htmlFor="theme" className={styles.label}>Theme:</label> <br />
            <select type="select" name="theme" id={styles.theme} className={styles.input} onChange={(e)=>setTheme(e.target.value)}>
                <option value="light">light</option>
                <option value="dark">dark</option>
            </select>
<br /><br />

        </div>
        <div className={styles.showbtndiv}>
            <button className={styles.showbtn} onClick={()=>handleclick()}>Show Modal</button>
        </div>
    </section>
}
like image 981
Shlok Jain Avatar asked Sep 06 '25 03:09

Shlok Jain


2 Answers

As you can read on the doc, you cannot have metadata in a client component. Here is the quote where they warn about that:

Both static and dynamic metadata through generateMetadata are only supported in Server Components.

So instead of having the whole page (or layout) as a client component, you could move the part where you need interactivity in a client file and import it into your server page, as they say:

To improve the performance of your application, we recommend moving Client Components to the leaves of your component tree where possible.

In your case, you could move the content of your current app/demo/page.js file inside a app/demo/demo.js file, for example, without the metadata, and import it:

// app/demo/page.js

import Demo from "./demo";

export const metadata = {
  title: 'Demo - ModalJS',
};

export default Page(){
 return <div><Demo/></div>
}
// app/demo/demo.js

'use client'

// ....

export default Demo(){
 return ...
}
like image 91
yousoumar Avatar answered Sep 07 '25 23:09

yousoumar


As every page.js can have a layout.js, you can leverage that to add the metadata onto the layout.js of that page.js.

In your case, it would look like this

/app/demo/page.js - stays the same

/app/demo/layout.js :

import { Metadata } from "next";
import Page from "./page";   // import your Demo's page

export const metadata: Metadata = {
  title: 'Your Title',
  description:
    "Your Description",
};
export default Page;

Automatically your metadata shall be added.

like image 25
Artemesian Avatar answered Sep 07 '25 23:09

Artemesian