gatsby developで動いていたのにデプロイしたらエラー

Gatsbyを用いた開発の中で、レスポンシブ対応で次のようなコードを書いて、開発環境(gatsby develop)で期待どおり動作しました。

<Menu width={410 < window.innerWidth ?  410 : '80%'} 

よしよしということで、Gatsby Cloud にデプロイしました。しかし、デプロイに失敗していることに気がついたのです。エラーメッセージは次でした。めちゃくちゃ親切です。

“window” is not available during server side rendering.

丁寧な説明へのリンクまであります。

SSG(静的サイトジェネレーション)は広義でサーバーサイドレンダリングであって、事前ビルド時はブラウザ環境でないので、windowオブジェクトは使えないということですね。

では、どうすればよいでしょうか?

単純には次のようにwindowが定義されているかどうかを確認すればよいようです。

// ビルド中にwindowを参照する関数を require するとエラーになる

const module = require("module") // エラー

// windowが使えることを確認して関数を require すればよい
if (typeof window !== `undefined`) {
  const module = require("module")
}

ブログ記事「Reactで画面サイズを取得するHooks | RyotArchLog」が

参考になりました。抜粋すると次の感じです。

src\util\useWindowDimensions.js

// 以下を参考にしました。
// https://ryotarch.com/javascript/react/get-window-size-with-react-hooks/

import { useCallback, useEffect, useState } from 'react';

export const useWindowDimensions = () => {
  const isClient = typeof window === 'object';
  const getWindowDimensions = useCallback(() => {
    return {
      width: isClient ? window?.innerWidth : 0,
      height: isClient ? window?.innerHeight : 0,
    };
  }, [isClient]);
  const [windowDimensions, setWindowDimensions] = useState(
    getWindowDimensions()
  );
  useEffect(() => {
    const onResize = () => {
      setWindowDimensions(getWindowDimensions());
    };
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, [getWindowDimensions]);
  return windowDimensions;
};

利用側(抜粋)

:
import { useWindowDimensions } from '../util/useWindowDimensions';
:
:
  const { width } = useWindowDimensions();

  return (
    <>
      :
      <Menu width={410 < width ? 410 : '80%'} />
      :
      :