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

by
Ali Hasan
app-router next.js next.js13

The Problem:

I’m using Next.js app router and want to change the title of the page using a client component. The title is currently being set in the layout and is the same for all pages. How can I set different titles for each page using a client component while using the app router and including a non-SSR page like Client?

The Solutions:

Solution 1: Create a new layout.js file in the client folder

When using a client component with app router in Next.js, you can change the title on a page by creating a new `layout.js` file in the `app/client` folder. This layout file will be specific to the client-side rendering of the page, and it can be used to set a custom title for the page.

// app/client/layout.js
export const metadata = {
  title: 'New Title'
}
export default function ClientLayout({ children }) {
  return children
}

In this example, the `metadata` object is used to set the title of the page to `New Title`. The `ClientLayout` component simply renders the children of the page, and it does not need to be modified.

To use this layout, you can import it into your client-side page and wrap the page’s content with the `ClientLayout` component.

// app/client/page.js
import ClientLayout from './layout'

export const getStaticProps = async () => {
  // Fetch data from an API
  return {
    props: {
      // Props for the page
    }
  }
}

export default function Page({ props }) {
  return (
    <ClientLayout>
      {/* Page content */}
    </ClientLayout>
  )
}

By using this approach, you can set a custom title for each page in your Next.js application, even when using the app router and including a non-SSR page like Client.

Solution:

To change the title on a page using a client component with the app router in Next.js, you can export a generateMetadata function from any layout.js or page.js file and use it to generate dynamic metadata for each page based on the fetched content. Here’s how you would do this:

// layout.js
export function generateMetadata() {
  return {
    title: 'My Dynamic Title',
    description: 'My Dynamic Description',
  };
}
// page.js
import { generateMetadata } from '../layout';

// For pages without getInitialProps (SSR)
export const getStaticProps = async () => {
  const metadata = generateMetadata();

  return {
    props: {
      metadata,
    },
  };
};

// For pages with getInitialProps (SSR)
export const getServerSideProps = async () => {
  const metadata = generateMetadata();

  return {
    props: {
      metadata,
    },
  };
};
// App.tsx
import { useRouter } from 'next/router';
import { Metadata } from '../components/Metadata';

export default function App({ Component, pageProps }) {
  const router = useRouter();
  const metadata = pageProps.metadata || generateMetadata(router.pathname);

  return (
    <Head>
      <title>{metadata.title}</title>
      <meta name="description" content={metadata.description} />
    </Head>
    <Metadata metadata={metadata} />
    <Component {...pageProps} />
  );
}

This approach allows you to define the metadata dynamically based on the fetched content and update the page title accordingly, even for client-side rendered pages using the app router.

Solution 3: Client-side with AppRouter

This solution uses the `useEffect` hook to change the page title on the client-side, after the page has been rendered. It takes advantage of the `appRouter`’s `use client` hook, which ensures that the code is only executed on the client-side.

Here’s how it works:

  1. Import the useEffect hook and the use client hook from next/router.
  2. Create a custom component, AppPage, that accepts a title prop and renders the page content.
  3. Inside the AppPage component, use the useEffect hook to set the document title to the provided title prop, but only if the title is not empty.
  4. Use the AppPage component as the layout for your blog pages, providing the appropriate title for each page.

This approach allows you to have different titles for each blog page, even when using the `appRouter` and a non-SSR page like `Client`.

Q&A

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

Use a non-server-side layout file and update document.title inside of useEffect when the client component is rendered.

Is there a simpler method?

You can use the next-seo package for easier implementation.

An alternative strategy?

Export a generateMetadata function from a layout or page file.

Video Explanation:

The following video, titled "Next.js App Router: Routing, Data Fetching, Caching - YouTube", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

leerob, VP of Developer Experience at Vercel, explains new concepts and foundations of Next.js app router, ...