How to change title on page using a client component with app router in Next.js?
Asked Answered
B

4

12

I'm building a blog using Next.js and I'm utilizing the new app router for navigation. However, I'm encountering an issue where every blog page displays the same title and description. Upon investigating the code, I found that the title and description are exported as Metadata() from the layout.js file, which seems to be the main cause of the problem. When I tried to use Metadata() in individual blog pages, it didn't work as expected.

Is there a way I can resolve this issue and have different titles and descriptions for each blog page, even when using the app router and including a non-SSR page like Client? I would appreciate any guidance or suggestions on how to approach this problem.

Baines answered 9/6, 2023 at 15:57 Comment(1)
Why would you use the directive 'use client' inside a blog page? If you don't need any javascript client interactivity, it's better for SEO and performacing to use a complete server-side component, your client js budle will thank you latter.Downhaul
E
6

If your page title is static then you can create a new layout.js file to export the metadata with the new title.

.
├── app/
│   ├── client/
│   │   ├── layout.js // Create new title here
│   │   └── page.js // 'use client'
│   ├── layout.js
│   └── page.js
├── package.json
└── next.config.js

So in the above example, if client/page.js has a 'use client' directive you can change the page title by creating a sibling layout.js file that simply renders the children and updates the title:

client/layout.js

export const metadata = {
  title: 'New Title'
}
export default function ClientLayout({ children }) {
  return children
}

If the page title is based on dynamic content from an API then you can use the above approach for a default server-side implementation, and then update the document.title inside of a useEffect when client/page.js is rendered.

Embitter answered 19/8, 2023 at 15:0 Comment(3)
HI, could you elaborate more on how to handle dynamic content from API? I am not sure how to get the dynamic content from page.tsx that is using use client in the layout.tsx.Orethaorferd
If it is dynamic from an api then you don’t need to define it in layout anymore, and can use an effect as described in this answer. Except you might be making the api call in your page.tsx so don’t pass as props.Embitter
With the answer that you suggested, it only allows to change the title via document.title. How can the meta description be changed as well?Orethaorferd
T
1

In Next.js 13, you can define static metadata by exporting a Metadata object from any layout.js or page.js file, but it's likely that you'll want to generate dynamic metadata for each page (metadata that depends on the fetched content for that page). To do dynamic metadata, you'll want to export a generateMetadata function

It's also possible that you'll find using a package like next-seo to be easier, although I didn't use it since Next.js 12 and don't know if it works with the new app directory.

Tachygraphy answered 13/6, 2023 at 8:40 Comment(2)
The OP specifically stated "client component"Contemporary
OP didn't actually stated that he was using the 'use client' directive inside blog pages. He just said he is using app router and a non-SSR page. This is the most correct answer because OP is asking for guidance on how to solve his problem and not how to use metadata inside a 'use client' component and the best guidance is to generate it on the server dynamicallyDownhaul
E
1

my way: AppPage.tsx

'use client'
const AppPage = ({ title, children, className, ...rest }) => {
  useEffect(() => {
    if (title) document.title = title
  }, [title])
  return <div className={className}>{children}</div>
}

Erratum answered 17/9, 2023 at 1:26 Comment(1)
That will change the title after the react component is already rendered. That's not a correct way to set title and description meta data, which are first meant to be read by SEO crawlers even before client's rendering.Downhaul
P
0

Having the meta attribute on a client component offsets the purpose for SEO and nextjs.

from https://nextjs.org/docs/app/api-reference/functions/generate-metadata#generatemetadata-function 👇

Good to know:

The metadata object and generateMetadata function exports are only supported in Server Components.

You cannot export both the metadata object and generateMetadata function from the same route segment.

Pound answered 11/3 at 9:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.