Maru
Maru

Reputation: 95

【Next.js】dynamic head tags are not reflected

Next.js next/link head tag and next-seo OGP are not reflected. I have been working on this for over 5 hours and have not been able to solve the problem&-(

The only tag that is adapted is the one in the Head of _document.js.

When I look at the HEAD from the browser validation, I see what I set in all of the HEADs: next/link, next-seo, and _document.js. However, I have tried a number of OGP verification tools and they all only show the tags set in the HEAD of _document.js.

Can someone please help me :_(

_app.js

import { useEffect } from 'react'
import { useRouter } from 'next/router'
import Script from 'next/script'
import { Provider } from "react-redux"
import { PersistGate } from 'redux-persist/integration/react'
import redux, { persistor } from '../components/store/redux.js'
import * as gtag from '../lib/gtag.js'
import { GA_TRACKING_ID } from '../lib/gtag'
import { DefaultSeo } from 'next-seo'
import SEO from '../../next-seo.config'
import Header from '../components/block/Header'
import Footer from '../components/block/Footer'

export default function App({ Component, pageProps }) {
    const router = useRouter()
    useEffect(() => {
        const handleRouteChange = (url) => {
            gtag.pageview(url)
        }
        router.events.on('routeChangeComplete', handleRouteChange)
        return () => {
            router.events.off('routeChangeComplete', handleRouteChange)
        }
    }, [router.events])

    return (
        <Provider store={redux}>
            <PersistGate loading={null} persistor={persistor}>
                <DefaultSeo {...SEO} />

                {/* Analytics */}
                <Script
                    async
                    src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
                />
                <Script
                    dangerouslySetInnerHTML={{
                        __html: `
                        window.dataLayer = window.dataLayer || [];
                        function gtag(){dataLayer.push(arguments);}
                        gtag('js', new Date());
                        gtag('config', '${GA_TRACKING_ID}', {
                        page_path: window.location.pathname,
                        });
                    `,
                    }}
                />
                <Header />
                <Component {...pageProps} />
                <Footer />
            </PersistGate>
        </Provider>
    )
}

_document.js

import Document, { Html, Head, Main, NextScript } from 'next/document';
class MyDocument extends Document {
    static async getInitialProps(ctx) {
        const initialProps = await Document.getInitialProps(ctx);
        return { ...initialProps };
    }

    render() {
        return (
        <Html lang="ja">
            <Head>
                <meta charSet="UTF-8" /> 
                <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
            </Head>
            <body>
                <Main />
                <NextScript />
            </body>
        </Html>
        );
    }
}

export default MyDocument;

Page.js

import React from "react"
import { NextSeo } from 'next-seo'

const Page = () => {
    const title = "title"
    const description = "description"
    const url = "https://test.com"

    return (
        <div>
            <NextSeo
                title={title}
                description={description}
                url={url}
                canonical={url}
                openGraph={{
                    ur: url,
                    title: title,
                    description: description,
                    type: "article"
                }}
            />
            <div>test</div>
        </div>
    )
}

export default Page

next-seo.config.js

export default {
    defaultTitle: "defaulttitle",
    canonical: "https://test.com/",
    description: "defaultDescription",
    twitter: {
        handle: "@twitter",
        site: "@twitter",
        cardType: 'summary_large_image',
    },
    openGraph: {
        type: "website",
        locale: 'ja_JP',
        title: "defaultTitle",
        description: "defaultDescription",
        site_name: "Test Site",
        url: "https://test.com/",
        images: [
        {
            url: "https://test.com/test.png",
            width: 800,
            height: 600,
            alt: "Image",
        }],
    },
    additionalLinkTags: [
        {
            rel: 'icon',
            href: 'https://test.com/favicon.ico',
        },
        {
            rel: 'apple-touch-icon',
            href: 'https://test.com/favicon.ico',
            sizes: '76x76'
        }
    ]
}

Upvotes: 1

Views: 1730

Answers (1)

hangindev.com
hangindev.com

Reputation: 4873

According to the docs of redux-persist,

PersistGate delays the rendering of your app's UI until your persisted state has been retrieved and saved to redux.

which means at build time, only null is rendered.

If <DefaultSeo /> does not rely on the data in the redux store, try placing it as a silbing of <Provider />, instead of children.

return (
  <>
    <DefaultSeo {...SEO}/>
    <Provider>...</Provider>
  </>
)

Upvotes: 4

Related Questions