简体   繁体   中英

How can I create dynamic titles in next.js <head> section?

I have a fully functioning website but the head sections doesn't retrieve page specific <title> and <meta description> .

For example, if I'm on the about page, with the title tag "About me" I would like to have "About me" rendered in the <title> tag. What I basically need is to load props, vars or something similar in my Head component that consist of an actual title and description. I've already read about some examples in the official documentation but there are no examples with updating the head with dynamic data.

This is the current code of my component:

import React from 'react';
import NextHead from 'next/head';

const Head = ({ title, description }) => (
    <NextHead>
        <meta charSet="UTF-8" />
        <title>My Website{title}</title>
        <meta name="description" content={description || ''} />
        <meta name="viewport" content="width=device-width, initial-scale=1" key="viewport" />
    </NextHead>
);

I've created a Layout.js component for the posts and pages. The <Head> I described earlier is imported in the layout component.

import React from 'react';
import Head from '../components/Head';


export default ({ children, as, settings = {}, title="default text" }) => (
    <main>
        <Head>
            <title>{title}</title>
        </Head>
        <div className="app__container">
            <div className="row">{children}</div>
        </div>
    </main>
);

I expected that when I'm for example at /work/great-client I would see an updated <title> tag with great-client

I found this solution a bit simpler and with fewer lines of code.

_app.js:

  export default function MyApp({ Component, pageProps }) {
  return (
    <>
      <Head>
        <title>{Component.title}</title>        
      </Head>
      <Layout>
        <Component {...pageProps} />
      </Layout>
    </>
  );
}

Home.js:

Home.title = 'Homepage';
export default function Home() {
  return (
    <>
      /* Some code */
    </>
  );
}

It should be:

import React from 'react';
import Head from '../components/Head';

export default ({ children, as, settings = {}, title="default text" }) => (
    <main>
        <Head title={title}>
        <div className="app__container">
            <div className="row">{children}</div>
        </div>
    </main>
);

If you want to use it as children of Head, then you have to modify your Head component:

import React from 'react';
import NextHead from 'next/head';

const Head = ({ title, description, children }) => (
    <NextHead>
        <meta charSet="UTF-8" />
        {children}
        <meta name="description" content={description || ''} />
        <meta name="viewport" content="width=device-width, initial-scale=1" key="viewport" />
    </NextHead>
);

I got it working after trying a little more with the second example.

Little bit more explanation follows in the code below.

Below example code shows Post.js including a shared component <Layout> . In layout i've added and added {props.meta.title} . Now its possible to retrieve dynamic title tags for page/post specific.

const Post = props => {
    const {
        content,
        meta: { title },
    } = props;


    return (
        <Layout>
            <Head>
                <title>{props.meta.title}</title>
            </Head>
            <div className="post">
                <div className="content-inner">
                        <h1>{title}</h1>
                    <article dangerouslySetInnerHTML={{ __html: content }} />
                </div>
            </div>
        </Layout>
    );
};

Post.getInitialProps = function(reqOrContext) {
    const { slug } = reqOrContext.query;
    let content = require(`../work/${slug}.md`);
    const converter = new Converter({ metadata: true });
    content = converter.makeHtml(content);
    const meta = converter.getMetadata();
    return { content, meta };
};

export default withRouter(Post);
  1. Create a layout component

  2. Destructure children from props

  3. Add to title {children.type.name}

     console.log(children); return ( <> <Head> <title>{children.type.name.toLowerCase()}</title> </Head> <div className="layout">{children}</div> </> ); };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM