Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next 13 - error multiples <title> / <meta> on tag <head> #42268

Closed
1 task done
john-dufrene-dev opened this issue Oct 31, 2022 · 26 comments
Closed
1 task done

Next 13 - error multiples <title> / <meta> on tag <head> #42268

john-dufrene-dev opened this issue Oct 31, 2022 · 26 comments
Labels
area: app App directory (appDir: true) bug Issue was opened via the bug report template. locked

Comments

@john-dufrene-dev
Copy link

john-dufrene-dev commented Oct 31, 2022

Verify canary release

  • 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: Wed Aug 10 14:25:27 PDT 2022; root:xnu-8020.141.5~2/RELEASE_X86_64
Binaries:
Node: 16.13.1
npm: 8.19.2
Yarn: 1.22.19
pnpm: N/A
Relevant packages:
next: 13.0.0
eslint-config-next: 13.0.0
react: 18.2.0
react-dom: 18.2.0

What browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

next dev

Describe the Bug

When a create files

head.js :

export default async function Head({ params }) {
  return (
    <>
      <title>Title head</title>
      <meta name="description" content="Generated by head" />
    </>
  );
}

layout.js :

export default async function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <title>Title layout</title>
        <meta name="description" content="Generated by layout" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </head>
      <body>{children}</body>
    </html>
  );
}

Tags < title > and < meta > are not deleted, just add another tags in html structure :

Capture d’écran 2022-10-31 à 23 53 25

I tried with async function and normal functions,

Thank's

Expected Behavior

<title> and tag replacement

Link to reproduction

https://github.com/john-dufrene-dev/test-nextjs13

To Reproduce

npm run dev with this repository

@john-dufrene-dev john-dufrene-dev added the bug Issue was opened via the bug report template. label Oct 31, 2022
@johnrackles
Copy link
Contributor

That's interesting, because in #42239 I am not able to change the title at all like this, and I'm not getting any duplicate tags.
But our setup looks similar, although I tried with canary.

@professorhaseeb
Copy link

I have the same issue on 13.0.1-canary.4

if the layout <head> has <title> only then, otherwise #42239

@SergeySypalo
Copy link

SergeySypalo commented Nov 5, 2022

I have a similar issue, I'm using meta tags inside the body for schema org metadata, but all these metadata are moved to/rendered in the head section, creating multiple titles and other metatags.
NextJS 13.0.2

@leerob
Copy link
Member

leerob commented Nov 5, 2022

Just updated the docs - you should only use head special file instead of putting <head> tags in the root layout:

// app/head.js

export default async function Head() {
  return (
    <>
      <title>Title</title>
      <meta name="description" content="Generated by head" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <link rel="icon" href="/favicon.ico" />
    </>
  );
}
// app/layout.js

export default async function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

@johannes-rackles
Copy link

Then it might be worth it changing the default template that create next app produces, bc in there the root layout has the title 🙂

@balazsorban44
Copy link
Member

The default template has been fixed in #42357

@komzweb
Copy link

komzweb commented Nov 6, 2022

Should tags that are commonly used on all pages (eg favicon) also be moved to head.js? I have the following method working fine for now:

// app/layout.js

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </head>
      <body>{children}</body>
    </html>
  );
}
// app/head.js

export default function Head() {
  return (
    <>
      <title>Title</title>
      <meta name="description" content="Generated by head" />
    </>
  );
}
// app/blog/[slug]/head.js

export default function PostHead() {
  return (
    <>
      <title>Post Title</title>
      <meta name="description" content="Generated by post head" />
    </>
  );
}

@SergeySypalo
Copy link

komzweb, I'm doing more/less the same now, but previously I simply accessed the post title in layout via children.props.title
It was a much more convenient way instead of creating a separate head file for each post.
I'm not using API for posts (they are simply stored in js files, because of better SEO optimization possibilities, which are not available when JSON/markdown is in use).
Would be nice if someone from dev tell here how to access children's post title from the layout, if possible. As from the docs passing props and vice versa is not possible.

@timneutkens timneutkens added the area: app App directory (appDir: true) label Nov 6, 2022
@chukwumaokere
Copy link

on "next": "^13.0.3-canary.0",
With RootLayout without a and using head.tsx in the app dir I get
Uncaught Error: Hydration failed because the initial UI does not match what was rendered on the server.

And worst of all, the title doesnt change on page navigation even though each route has a head.tsx with the <title> being exported as a react fragment

@komzweb
Copy link

komzweb commented Nov 7, 2022

And worst of all, the title doesnt change on page navigation even though each route has a head.tsx with the <title> being exported as a react fragment

@chukwumaokere The docs have a workaround for that and it says "to be fixed in the future".

@SergeySypalo
Copy link

Updated today to NextJS 13.0.3, but the issue is still present, all my schema.org meta tags are moved from the body to the page head creating a mess of multiple titles and descriptions on the posts list page.

@christo9090
Copy link

And worst of all, the title doesnt change on page navigation even though each route has a head.tsx with the <title> being exported as a react fragment

@chukwumaokere The docs have a workaround for that and it says "to be fixed in the future".

I don't see the workaround for this in the docs. On navigation using the next.js Link, the head stays the same as the route you landed on and doesn't change with navigation.

Any fix for this?

@MakStashkevich
Copy link

MakStashkevich commented Jan 3, 2023

Dynamic header title & meta tags on NextJs 13

My solution (without duplicates headers):

I am faced with the problem of changing title and meta tags on the new version of NextJs 13

After a couple of hours, I found an elegant solution...

As it turned out, it is not necessary to use the head file.tsx

Therefore, we can easily create an empty head.tsx in the root of the /app folder:

// app/head.tsx

import React from 'react';

export default function RootHead() {
    return undefined;  // Disable root head
}

And then, in places where it is necessary to prescribe the usual <head/> and <meta/> from the HTML markup:

// app/page.tsx OR app/blog/[slug]/page.tsx

import React from "react";

export default function RootPage() {
    return (
        <div>
            // Set title & description without <Head/> components
            <title>Home</title>
            <meta name="description" content="My homepage"/>
          
            // Set page code
            <p>Other content...</p>
        </div>
    )
}

P.S. You can create a separate component called AppHead.tsx and add it where necessary by specifying parameters, for example:

// app/page.tsx OR app/blog/[slug]/page.tsx

import React from "react";
import AppHead from "./app-head.tsx";

export default function RootPage() {
    return (
        <div>
            // Set title & description with custom <AppHead/> component
            <AppHead title="Home" description="My homepage"/>
          
            // Set page code
            <p>Other content...</p>
        </div>
    )
}

P.P.S. If you are superman, then you can create a HeadProvider.tsx component and not write <AppHead/> in each file.

Example adding head context to your web application:

// app/layout.tsx

import React from "react";

import HeadProvider from "../context/head";
import AppHead from "./AppHead";

export default function RootLayout({children}: { children: React.ReactNode }) {
    return (
        <html lang="en">
        <HeadProvider>  // <-- this wrapper look like: <HeadContext.Provider>{children}</HeadContext.Provider>
            <AppHead/>  // <-- this component set <title/> & <meta/> from HeadContext
            <body>
                {children}  // <-- on any file we will get & change context: React.useContext(HeadContext);
            </body>
        </HeadProvider>
        </html>
    )
}

See gist code: https://gist.github.com/MakStashkevich/23e8059f3b018a3c6e8e811b1a2d59b9

I hope it will be useful. ❤️

@SergeySypalo
Copy link

MakStashkevich, now try to add any meta tag inside body, for example

<article itemScope itemType="https://schema.org/BlogPosting">
   <meta itemProp="title" content="My title" />
   <p>Bla-bla-bla</p>
</article>

And check if you have two titles in the head.

@MakStashkevich
Copy link

MakStashkevich, now try to add any meta tag inside body, for example

<article itemScope itemType="https://schema.org/BlogPosting">
   <meta itemProp="title" content="My title" />
   <p>Bla-bla-bla</p>
</article>

And check if you have two titles in the head.

Create HeadProvider and use hook on every page without duplicates <meta> tags, example:

const {setTitle} = useHead();
setTitle("bla-bla-bla");

@SergeySypalo
Copy link

SergeySypalo commented Jan 20, 2023

It doesn't solve the issue, meta tags are removed from the article body, so no rich schema org markup. Just tested on the latest Next JS 13.1.3.

@SergeySypalo
Copy link

Updated to 13.1.4 - the same issue, 13.1.5 - still there. Any updates from the developers?

@klarstrup
Copy link

We're also experiencing this issue on 13.1.5 with pages/ (not app/)

@SergeySypalo
Copy link

Hi there, is there anyone going to look into this ongoing issue?
Still the same in 13.1.6

@klarstrup
Copy link

Another clue for this happening with /pages too (still in 13.1.6) is that we are using suspense in that universe (via @tanstack/query)

@SergeySypalo
Copy link

So sad to see the issue is still here after almost 4 months discussion and present in the latest 13.2.1.
@ijjk is it something you can help with?

@SergeySypalo
Copy link

Found an interesting thing today, then decided to try from newly create NextJS 13.2.1 from scratch and use /app directory
npx create-next-app@latest --experimental-app
Then copied <div itemscope itemtype="https://schema.org/NewsArticle"> with its contents from https://developers.google.com/search/docs/appearance/structured-data/article
And it worked as expected 😀
When I compared what was is the difference between this project and a test one I have, the dealbreaker was itemProp in my test site vs itemprop in Google example, same applies to other item... Schema.org metadata.
I remember VSCode previously suggested me to change from all lowercase to 1 uppercase letter, otherwise highlighted a page as containing errors.
Going to move my devops blog to a newer version finally 🙂

@klarstrup
Copy link

Turns out my problem, which I think is in fact separate from this one, was caused in my project by using react@next (18.3.0-next-0f4a83596-20230110 to be precise). Returning to [email protected] has restored sanity to my project.

Repro for my actual bug: npx create-next-app@latest and npm install react@next react-dom@next, now any <meta> tags that were supposed to render within <div id="__next"> will render before it, right into <body>.

@klarstrup
Copy link

Turns out this was the erroneous behavior I was happening upon: facebook/react#26256

@leerob
Copy link
Member

leerob commented Sep 9, 2023

Closing this as stale since there is a new Metadata API since this issue was opened.

https://nextjs.org/docs/app/building-your-application/optimizing/metadata

@leerob leerob closed this as completed Sep 9, 2023
@github-actions
Copy link
Contributor

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

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: app App directory (appDir: true) bug Issue was opened via the bug report template. locked
Projects
None yet
Development

No branches or pull requests