最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - NextJs Metadata in "use client" - Stack Overflow

programmeradmin5浏览0评论

So the problem is I have a product page in which I'm getting metadata for that particular product page from backend i.e. from database using an API. I have to use a custom hook to fetch data from that API, Now the Problem is I can't use that metadata from the "use client" directive.

I can't share my whole code As it's 500+ lines so here's a glimpse what I am trying to do!

"use client"
import React from "react";
import useGetData from "./useGetData";

const Page = () => {
   const { data } = useGetData();
   return (
      <div>
      Some use of {data}
      </div>
   );
}

export default Page;

const GenerateMetaDataTags = () => {
  const { propId } = useParams();
  const { data, loading, error } = useGetData(propId);
  const metaData = {};

  data.forEach((ele) => {
    metaData[ele.name] = ele.content;
  });

  if (!loading) {
    return metaData;
  }
};

export const metadata = GenerateMetaDataTags();

I want this Data to update on the client side after fetching from the database.

I tried a lot of different approaches like using layout.js and all but I have to use hook to get the data from database and the hook will always need the "use client";

So the problem is I have a product page in which I'm getting metadata for that particular product page from backend i.e. from database using an API. I have to use a custom hook to fetch data from that API, Now the Problem is I can't use that metadata from the "use client" directive.

I can't share my whole code As it's 500+ lines so here's a glimpse what I am trying to do!

"use client"
import React from "react";
import useGetData from "./useGetData";

const Page = () => {
   const { data } = useGetData();
   return (
      <div>
      Some use of {data}
      </div>
   );
}

export default Page;

const GenerateMetaDataTags = () => {
  const { propId } = useParams();
  const { data, loading, error } = useGetData(propId);
  const metaData = {};

  data.forEach((ele) => {
    metaData[ele.name] = ele.content;
  });

  if (!loading) {
    return metaData;
  }
};

export const metadata = GenerateMetaDataTags();

I want this Data to update on the client side after fetching from the database.

I tried a lot of different approaches like using layout.js and all but I have to use hook to get the data from database and the hook will always need the "use client";

Share Improve this question edited Feb 9, 2024 at 16:35 VLAZ 29.1k9 gold badges63 silver badges84 bronze badges asked Feb 9, 2024 at 16:34 Shivam SharmaShivam Sharma 4415 silver badges15 bronze badges 2
  • Why do you need a hook to get data from the database? Can you use a server action instead? This would give you client-side updates if you tag and revalidate your fetch call in the data cache. – PhilB Commented Feb 9, 2024 at 16:40
  • Still, It will need a "use client" tag to reflect changes in the page. – Shivam Sharma Commented Feb 9, 2024 at 18:00
Add a ment  | 

4 Answers 4

Reset to default 5

This seems to have gotten easier now with the app router.

You can just add Your dynamic title collected from useState here anywhere in a ponent that has "use client"

Assuming data contains an seoTitle and an seoDescription, this could be done like the following.

Metadata.tsx

interface Props {
  seoTitle: string;
  seoDescription: string;
}

export default function Metadata({ seoTitle, seoDescription }: Props) {
  return (
    <>
      <title>{seoTitle}</title>
      <meta name="description" content={seoDescription} />
    </>
  );
}

Page.tsx

 "use client"
 import { useState } from "react";
 import useGetData from "./useGetData";

 const Page = () => {
    const { data } = useGetData();
    return (
      <>
        <Metadata seoTitle={data.seoTitle} seoDescription={data.seoDescription} />
        <div>
          Some use of {data}
        </div>
     </>
   );
 }

As per the code here, you have fetched the meta data in metadata. Now you might need to populate it in the return of the Page method. Also consider calling GenerateMetaDataTags() before the return and consider removing the call export const metadata = GenerateMetaDataTags(); in the last line. When you say metadata, I am assuming it is the data in the meta tags which goes in the Head ponent like.

import Head from 'next/head'

...
...
const Page = () => {
   const { data } = useGetData();

   const metadata = GenerateMetaDataTags();

  return (
<>
    <Head>
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <meta name="msapplication-TileColor" content="#000000" />
      <meta name="msapplication-config" content="/favicon/browserconfig.xml" />
      <meta name="ele1" content={metaData["ele1"]} />
      <meta name="ele2" content={metaData["ele2"]} />
    </Head>

    <SomeComponent>
     <div>
      Some use of {data}
     </div>
    </SomeComponent>

</>);
}
...
...

You can read more about rendering for pages router, or for app router.

i'm facing the same problem, i tried several approach without success, i'm using next js 14 and mongodb with several nested routes, so the only clean way to fetch the data is client side ( using "use client" for useeffect ), now all pages work very well except the seo part :) , because if you use 'use client' within the app router you can't use the export const metadata or the .

if they had let the nextseo, the head ponent ... it was very easy to deal with seo

as the docs says you cannot generate metadata in a client ponent.

发布评论

评论列表(0)

  1. 暂无评论