Next.jsでどうしてもReact Helmetを使いたい場合の覚書
Next.jsでOGPなどのmetaタグを取り扱う場合、next/headを使うのが基本です。が、別のアプリからマイグレした場合などで、どうしてもReact helmetからの移行が難しいケースもあります。 そんな場合の […]
広告ここから
広告ここまで
目次
Next.jsでOGPなどのmetaタグを取り扱う場合、next/head
を使うのが基本です。が、別のアプリからマイグレした場合などで、どうしてもReact helmetからの移行が難しいケースもあります。
そんな場合の対処法について、Next.jsのExampleをベースに、自分向けにまとめました。
React HelmetはNext.jsでそのまま動かない
原因を深掘りしていないので不明ですが、React Helemetで書いたmetaタグがNext.jsのSSRでレンダリングされていない現象に遭遇しました。
基本的にnext/head
でReact Helmetができることはカバーできるので、そっちに切り替えるのが正攻法ではあると思います。が、Exampleでwith-react-helmet
があったことと、対応にあまり時間をかけたくなったことの2点からそのままHelmetを使うことに決定。
_document.tsx
でreact-helmet
のSSR処理を実行
ExampleのコードをTypeScriptで動くようにしたものが以下です。any
で乗り切っていますが、将来的にnext/head
に変える前提のため省力化したためです。
import React from "react";
import { Helmet } from "react-helmet";
import Document, { Html, Head, Main, NextScript } from "next/document";
export default class MyDocument extends Document<{
helmet: any;
}> {
static async getInitialProps(args: any) {
const documentProps = await super.getInitialProps(args);
return { ...documentProps, helmet: Helmet.renderStatic() };
}
// should render on <html>
get helmetHtmlAttrComponents() {
return this.props.helmet.htmlAttributes.toComponent();
}
// should render on <body>
get helmetBodyAttrComponents() {
return this.props.helmet.bodyAttributes.toComponent();
}
// should render on <head>
get helmetHeadComponents() {
return Object.keys(this.props.helmet)
.filter((el) => el !== "htmlAttributes" && el !== "bodyAttributes")
.map((el) => this.props.helmet[el].toComponent());
}
render() {
return (
<Html {...this.helmetHtmlAttrComponents}>
<Head>{this.helmetHeadComponents}</Head>
<body {...this.helmetBodyAttrComponents}>
<Main />
<NextScript />
</body>
</Html>
);
}
}