next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Next.js 13: Client side navigation does not update head

Open shadcn opened this issue 1 year ago • 4 comments

Verify canary release

  • [X] I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
	Platform: darwin
	Arch: x64
	Version: Darwin Kernel Version 21.6.0: Mon Aug 22 20:17:10 PDT 2022; root:xnu-8020.140.49~2/RELEASE_X86_64
Binaries:
	Node: 16.18.0
	npm: 8.19.2
	Yarn: 1.22.19
	pnpm: 7.13.5
Relevant packages:
	next: 13.0.2-canary.2
	eslint-config-next: 13.0.0
	react: 18.2.0
	react-dom: 18.2.0

What browser are you using? (if relevant)

Bug present in all browsers

How are you deploying your application? (if relevant)

Local and Vercel

Describe the Bug

On client side navigation, head.tsx is not updating the DOM. Works fine when you force a refresh.

Using the current file structure:

├── posts
│   └── [id]
│       ├── head.tsx
│       └── page.tsx
├── head.tsx
├── layout.tsx
└── page.tsx

See repo at: https://github.com/shadcn/next-debug-head

Expected Behavior

Expected the <title /> tag to be updated on client side navigation.

Link to reproduction

https://next-debug-head.vercel.app

To Reproduce

  1. Click on Post one. Check the title.
  2. Refresh the page. Check the title again.

shadcn avatar Nov 03 '22 15:11 shadcn

OK looks like a known issue. I just found the following in the docs:

Warning: Currently, the Head export does not re-render on client-side transitions, only on > initial render. To work around this for

, you can use a client component with > useEffect that updates document.title. This will be fixed soon in a future release.

https://beta.nextjs.org/docs/api-reference/file-conventions/head

shadcn avatar Nov 03 '22 15:11 shadcn

can you impl the workaround?

Geczy avatar Nov 04 '22 21:11 Geczy

So far this is what I've been using. Hope it helps.

// ./components/TitleUpdater.tsx

"use client";

import { useEffect } from "react";

const TitleUpdater = ({ title }: { title: string }) => {
   useEffect(() => {
      document.title = title;
   });

   return null;
};

export default TitleUpdater;

And you just place it on any of your pages passing in the title like so

// ./app/[userId]/page.tsx

import TitleUpdater from '../../components/TitleUpdater.tsx';

const getUser = async (userId: string) => {...}; // call to api to get user data

const UserPage = async ({ params }: UserPageProps) => {
   const { userId } = params;
   const { name }: UserType = await getUser(userId);

   const title = `${name} • Your website`;

   return (
      <>
         <TitleUpdater title={title} />
         <main>
            // your page content
         </main>
      </>
   );
}

export default UserPage;

You should still use the new head file if you want the title to be picked up on first render by the server since the update is triggered only on client side.

milovangudelj avatar Nov 07 '22 00:11 milovangudelj

meta is also not update. is a way to update it ?

st1ng7ay avatar Nov 17 '22 10:11 st1ng7ay

13.0.4 solve the problem

st1ng7ay avatar Nov 18 '22 05:11 st1ng7ay

Confirmed. Fixed by https://github.com/vercel/next.js/pull/42904. Closing this. Thanks everyone.

shadcn avatar Nov 18 '22 11:11 shadcn

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

github-actions[bot] avatar Dec 18 '22 12:12 github-actions[bot]