6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GatsbyJSでlocation(現在のURL)を取得する方法

Last updated at Posted at 2020-12-30

GatsbyJSではbuilding中はブラウザーと切り離されるためwindowメソッドからのlocation取得の手法が使えません(参考:CSS TRICKS - How to Get the Current Page URL in Gatsby)

そのためGatsbyJSにデフォルトで入っている機能を使って取得しないといけないため少しややこしいです。
最初は import { useLocation } from 'react-router-dom' から引っ張れるかなと思ったら上手くいかず。

※@react/routerではなく@reach/routerです。記載ミスのため修正しました。

propsのlocationを親要素から取り出す

GatsbyJSの公式サイト Location Data from Props に記載されているようにクライアントサイドのルーティングにはデフォルトで @reach/router @reach/router(公式ドキュメント)が使用されています。
したがってpropsにlocationが渡されていることになるのでこれを利用します。

これは自分のケースですがlayout.jsファイルからlocationを呼び出しそれを引っ張ってきました。

layout.tsx
import React, {FC} from 'react'
// 省略
const Layout: FC = ({ location }) => {
 return (
  <div>
   <Header pathname={location.pathname} />
  </div>
)
}
header.tsx
import React from 'react'
// 省略
const Layout: FC<{pathname: string}> = ({ pathname }) => {
 return (
  <div>
   {pathname === '/' && (
        <div>
          hogehoge
        </div>
      )}
  </div>
)
}

上記のような形で引っ張ってこれました。
ちなみにlocationオブジェクトの中身は下のようになります。

{
  hash: ""
  host: "localhost:8000"
  hostname: "localhost"
  href: "http://localhost:8000/login/"
  key: "initial"
  origin: "http://localhost:8000"
  pathname: "/login/"
  port: "8000"
  protocol: "http:"
  search: ""
  state: null
}

詰まったところ

最初からHeaderコンポーネントに{ location }を引っ張ってこようとしてずっとエラーが生じました

Property 'location' does not exist on type '{ children?: ReactNode; }'.ts(2339)

怒られた通りに色々やってみてもダメでわからなかったのですがすでに述べたように親コンポーネントであるlayout.tsxからlocationを引っ張ってきたことで解決しました。
冒頭でも述べたように @reach/router の挙動がもとにあります。

また、

layout.tsx
import React, {FC} from 'react'
// 省略
const Layout: FC = ({ location }) => {
 return (
  <div>
   <Header location={location} />
  </div>
)
}

layoutコンポーネントから { location } をそのまま受け渡してHeaderコンポーネントのほうで { location } を受け取ろうとしても先のTypeエラーが生じてダメでした。
名前をlocation以外に変えて受け取る必要があります。

SSRでlocationを取得する方法

gatsby-ssr.jsでSSRメソッドが利用できるのでそれを利用して各コンポーネントにSSR処理でlocationを取得する方法があります。

ここはまだ模索中です。自分のコードではなくCSS TRICKS - How to Get the Current Page URL in Gatsby)からコードを引用させてもらいました。

gatsby-ssr.js
const React = require('react');
const config = require('./gatsby-config');

exports.onRenderBody = ({ pathname, setHeadComponents }) => {
  setHeadComponents([
    <link rel="canonical" href={`${config.siteMetadata.siteURL}${pathname}`} />,
  ]);
};

onRenderBodyメソッドを利用することでグローバルにコンポーネントを追加することができます。
参考:Gatsby Server Rendering APIs

setHeadComponentsとは各ページのヘッダーにJSXをセットするためのメソッドです。
config.siteMetadata.siteURLはgatsby-config.jsで設定した siteMetadata {省略} のプロパティに記載したURLです。
pathnameはドメインとhttpプロトコルを含まないslugです

なぜか上手くいかず

TypeScriptの環境なのかなんなのかわかりませんでしたがlocalhost:8000上ではヘッダーにが表示されず。
わかり次第、追記します。

ただし、本記事とは無関係ですがとりあえずSSRを試すという意味合いで下のコードは走りました。(bodyタグにクラス名をSSRの処理で追加)

gatsby-ssr.js
exports.onRenderBody = ({ setBodyAttributes }, pluginOptions) => {
  setBodyAttributes({
    className: "body-test-className",
  })
}
6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?