next.jsjson-ldapp-router

How can I remove parent component's script tag in child component layout.tsx?


I'm using app router from next.js. I'd like to add jsonLd datas for both pages, "/blog" and "/blog/[searchKeyword]". but I met some problems about this process.

blog > layout.tsx

 return (
<>
    <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
        id="jsonLd-blog"
    />
    {children}
</> );

blog/[searchKeyword] > layout.tsx

return ( <>
    <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
        id={jsonLd-${params.searchKeyword}}
    />
    {children}
</> );
  1. First, in the page "/blog/[searchKeyword]", it has not only jsonLd from its layout.tsx but also from "/blog"'s layout.tsx.
  2. Second, I tried to remove the parent jsonld script code by using 'remove()' method with their id, such as 'jsonLd-blog' like below.
"use client";

import { useEffect } from "react";

const RemoveJsonScript: React.FC<{ elementId: string }> = ({ elementId }) => {
  useEffect(() => {
    const oldJsonLds = document.getElementById(elementId);
    if (oldJsonLds) {
      oldJsonLds.remove();
    }
  }, []);

  return <></>;
};

export default RemoveJsonScript;

3. Third, however, it triggered an error below, regardless of whether it is used in server component or client component..

Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

4. In addition, it does not work in <Head> tag from "next/head", but only in <head> tag. This issue is not related to above three issues, but I wonder why it does.

I cannot know how to solve this problem. Next.js is the greatest framework for SEO I've used, but this error make me frustrated.. I need your help.

I want get rid of the parent's jsonLd script tag, without any error message like 'Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.'


Solution

  • This behavior is expected as layout.tsx will wrap all it's children layouts or pages. So if you have /blog/layout.tsx and /blog/[searchKeyword]/layout.tsx, the component tree for /blog/[searchKeyword]/page.tsx will look like this:

    <BlogLayout>
      <BlogSearchKeywordLayout>
        <BlogSearchKeywordPage />
      </BlogSearchKeywordLayout>
    </BlogLayout>
    

    The best solution for you is to place your json-ld script tags in the /blog/page.tsx and /blog/[searchKeyword]/page.tsx