如何将 <head> 插入 Next.js 中动态渲染的客户端组件中

问题描述 投票:0回答:1

我正在尝试将标题标签插入到 next.js 中动态渲染的客户端组件的头部。

但是当我尝试插入 Head 标签时出现 Hydration 错误。

'use client';
import Article from '@/app/components/layouts/Article';
import Image from 'next/image';
import Link from 'next/link';
import data from '../portfolio.json';

//function to query the param requested portfolio
const getPost = (params: string) => {
  const { portfolio } = data;
  return portfolio.find((_, index) => index == Number(params));
};

export default function Page({ params }: { params: { id: string } }) {
  const current = getPost(params.id);

  return (
    <>
      <Article>
        <head>
          <title>{current?.name}</title>
          <meta name='description' content={current?.short_description} />
        </head>
        <article className='flex min-h-screen max-w-full flex-col  items-center p-12 bg-light  dark:bg-primary'>
          <div className='flex flex-col items-center mt-14 bg-lighdark:bg-primary '>
            <div className='max-w-2xl  '>
              <h1 className='text-center text-black dark:text-secondary text-2xl md:text-4xl mb-16 md:mt-[8rem] font-bold '>
                {current?.name}
              </h1>
              <div className='w-full transition-transform duration-200 hover:scale-95'>
                <Link className='button ' href='/portfolio'>
                  &lt; Go Back
                </Link>
              </div>
              <p className='my-16 text-sm text-black dark:text-white mt-20 indent-20 '>
                {current?.short_description}
              </p>

              <section className='w-full '>
                <div className='flex flex-col items-left md:ml-10'>
                  {current?.links.front_end && (
                    <div className='text-xs my-1'>
                      <span className='mr-1 bg-[#405a4d] dark:bg-[#34403a] text-[#72a584] px-1 rounded-sm'>
                        WEBSITE:
                      </span>
                      <a
                        className='text-pink-600 dark:text-accent hover:underline'
                        href={current?.links.front_end}
                      >
                        {current?.links.front_end}
                        {/* @ts-ignore */}
                        <box-icon name='link-external' size='xs' color='pink'>
                          {/* @ts-ignore */}
                        </box-icon>
                      </a>
                    </div>
                  )}
                  {current?.links.back_end && (
                    <div className='text-xs my-1'>
                      <span className='mr-1 bg-[#405a4d] dark:bg-[#34403a] text-[#72a584] px-1 rounded-sm'>
                        BACKEND:
                      </span>

                      <a
                        className='text-pink-600 dark:text-accent hover:underline'
                        href={current?.links.back_end}
                      >
                        {current?.links.back_end}
                        {/* @ts-ignore */}
                        <box-icon name='link-external' size='xs' color='pink'>
                          {/* @ts-ignore */}
                        </box-icon>
                      </a>
                    </div>
                  )}
                  {current?.links.github && (
                    <div className='text-xs my-1'>
                      <span className='mr-1 bg-[#405a4d] dark:bg-[#34403a] text-[#72a584] px-1 rounded-sm'>
                        GITHUB:
                      </span>
                      <a
                        className='text-pink-600 dark:text-accent hover:underline'
                        href={current?.links.github}
                      >
                        {current?.links.github}
                        {/* @ts-ignore */}
                        <box-icon name='link-external' size='xs' color='pink'>
                          {/* @ts-ignore */}
                        </box-icon>
                      </a>
                    </div>
                  )}
                  <div className='text-xs mt-4'>
                    <span className='mr-1 bg-[#405a4d] dark:bg-[#34403a] text-[#72a584] px-1 rounded-sm'>
                      STACK:
                    </span>
                    <a
                      className='text-pink-600 dark:text-accent '
                      href={current?.links.github}
                    >
                      {current?.stack}
                      {/* @ts-ignore */}
                      <box-icon name='coin-stack' size='xs' color='pink'>
                        {/* @ts-ignore */}
                      </box-icon>
                    </a>
                  </div>
                  <div className='text-xs my-1'>
                    <span className='mr-1 bg-[#405a4d] dark:bg-[#34403a] text-[#72a584] px-1 rounded-sm'>
                      FEATURES:
                    </span>
                    <a
                      className='text-pink-600 dark:text-accent '
                      href={current?.features}
                    >
                      {current?.stack}
                      {/* @ts-ignore */}
                      <box-icon name='coin-stack' size='xs' color='pink'>
                        {/* @ts-ignore */}
                      </box-icon>
                    </a>
                  </div>
                </div>
              </section>
              <section className='mt-16'>
                <div className='flex items-center flex-col '>
                  {current?.images.map((links, index) => (
                    <Image
                      className='rounded-lg my-5'
                      alt={current.name + index}
                      src={`/portfolio/images/${links}`}
                      height={300}
                      width={600}
                      quality={100}
                    />
                  ))}
                </div>
                <div className='flex justify-center flex-wrap'>
                  {current?.imagesMobile.map((links, index) => (
                    <Image
                      className='rounded-lg my-5 inline-block mx-5'
                      alt={current.name + index}
                      src={`/portfolio/images/${links}`}
                      height={300}
                      width={200}
                      quality={100}
                    />
                  ))}
                </div>
              </section>
            </div>
          </div>
        </article>
      </Article>
    </>
  );
}

我尝试插入它,它成功了!我可以在 Google Chrome 选项卡上看到标题(这就是我想要的!)

但是,nextjs 优雅地让我知道——像往常一样出现了水合错误

reactjs next.js metadata hydration
1个回答
0
投票

如果您的

generateMetadata
标签中需要动态数据,则必须使用
head
。 Head 组件已被generateMetadata API 取代。 查看 Nextjs 文档

对于您的用例,请尝试以下操作:

export default function Page() {
  return ...;
}

export async function generateMetadata(): Promise<Metadata> {
  const data = await getMyData();
  return {
    // return your metadata here
  };
}
© www.soinside.com 2019 - 2024. All rights reserved.