When using React.Fragment or anArray as a child of the next/head component, all the tags that are inside of them are not being rendered/parsed correctly into the DOM.
I have an use case where I need to create a component that wraps head elements.
This component lives in a repository that is agnostic to NextJS, so I cannot encapsulate those head elements with the Head component provided by next/head directly.
Currently I'm returning those elements wrapped by a React.Fragment element, so it looks something like this:
<React.Fragment>
<title>{props.title}</title>
<meta name="description" content={props.description} />
</React.Fragment>
And in the repository where I'm using NextJS, I'm using that component like this:
<div>
<Head> // This comes from next/head
<ComponentThatRendersHeadTags title="Title" description="description" />
</Head>
...
</div>
However, when I mount that component and go to the head tag in my DOM, I can see that the title tag is being rendered with empty content (looks something like this: <title></title> and the meta tags are being rendered correctly but they don't have the next-head class that should be applied to them (don't know if this can cause problems when using Links or the Router itself).
I'm currently doing a workaround to this where I'm sending the next/head component as a prop to the component rendering the tags, so it looks something like this:
const { WrapperComponent } = props
return (
<WrapperComponent>
<title>{props.title}</title>
<meta name="description" content={props.description} />
</WrapperComponent>
)
And this approach is working correctly, filling the title tag with content and applying the next-head class to all of them.
P.S.: I actually don't know if this behavior of not accepting React.Fragment in Head is expected 馃槄
Even though the workaround is working correctly, it would be cool if the next/head component supports React.Fragment or even an Array as a child.
7.0.2Heys guys, I have been using NextJS for over a year now and I really love it 鉂わ笍
Keep the hard work 馃挭 thanks for everything 馃槃
I don't think we should change the next/head API, it's been working fine for 99% of use cases, it accepts direct components as children and that should be enough to cover use cases. The reason I don't want to change the API is that I don't think that we should make the next/head module bigger / shipping code that won't be used by most users or when there is a workaround. I hope this makes sense to you.
@timneutkens I understand your point but I'm confused that this is not an issue for more people. Don't other people create a MetaTag component of sorts where they can simply set all the meta tags shared between pages but also customise them based on the current page?
If I don't use the component I need to manually copy this and change 21 properties for each page? 馃槶
MetaTag component
import React, { Fragment } from "react";
export default ({ title, description, keywords, url = "", language }) => (
<Fragment>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<meta name="theme-color" content="#118b92" />
<link rel="manifest" href="/static/manifest/manifest.json" />
<title>{title}</title>
<meta name="description" content={description} />
<meta name="keywords" content={keywords} />
<meta name="author" content="..." />
<meta property="og:site_name" content="..." />
<meta property="og:title" content={title} />
<meta property="og:url" content={`...${language}/${url}`} />
<meta property="og:image" content={...} />
<meta property="og:description" content={description} />
<meta property="og:type" content="website" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={...} />
<meta name="twitter:card" content="summary_large_image" />
<link rel="alternate" href={`...${url}`} hrefLang="nl" />
<link rel="alternate" href={`...${url}`} hrefLang="en" />
<link rel="alternate" href={`...${url}`} hrefLang="fr" />
<link rel="icon" type="image/png" href={...} sizes="16x16" />
<link rel="icon" type="image/png" href={...} sizes="32x32" />
<link rel="apple-touch-icon" href={...} />
<link rel="apple-touch-icon" sizes="180x180" href={...)} />
<link rel="mask-icon" href={...)} color="#d04819"/>
<link rel="shortcut icon" href={...} />
<meta name="theme-color" content="#118b92" />
</Fragment>
);
You can have multiple usages of next/head actually, or dependency inject @AlexisGlez was doing already
You can have multiple usages of
next/headactually, or dependency inject @AlexisGlez was doing already
I'm not sure what you mean with your answer, do you have an example where I can make sure that I don't need to manually copy the tags listed in my previous reaction?
import Head from 'next/head'
export default ({ title, description, keywords, url = "", language }) => (
<Head>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<meta name="theme-color" content="#118b92" />
<link rel="manifest" href="/static/manifest/manifest.json" />
<title>{title}</title>
<meta name="description" content={description} />
<meta name="keywords" content={keywords} />
<meta name="author" content="..." />
<meta property="og:site_name" content="..." />
<meta property="og:title" content={title} />
<meta property="og:url" content={`...${language}/${url}`} />
<meta property="og:image" content={...} />
<meta property="og:description" content={description} />
<meta property="og:type" content="website" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={...} />
<meta name="twitter:card" content="summary_large_image" />
<link rel="alternate" href={`...${url}`} hrefLang="nl" />
<link rel="alternate" href={`...${url}`} hrefLang="en" />
<link rel="alternate" href={`...${url}`} hrefLang="fr" />
<link rel="icon" type="image/png" href={...} sizes="16x16" />
<link rel="icon" type="image/png" href={...} sizes="32x32" />
<link rel="apple-touch-icon" href={...} />
<link rel="apple-touch-icon" sizes="180x180" href={...)} />
<link rel="mask-icon" href={...)} color="#d04819"/>
<link rel="shortcut icon" href={...} />
<meta name="theme-color" content="#118b92" />
</Head>
);
Most helpful comment