react-simplemde-editor
というパッケージを使用したところ
navigator is not defined
というエラーが吐かれました。
こういうエラーが一番厄介ですよね。
解決策
結論から言うと、dynamic
を使って動的にコンポーネントを読み込むことで解決できます。
import dynamic from "next/dynamic";
const SimpleMDE = dynamic(() => import("react-simplemde-editor"), { ssr: false });
// 省略
このように問題が起きているであろうコンポーネントをdynamic
で読み込んであげるとエラーは解消されました。
理由
あくまで僕個人の解釈なので合っているかは分かりませんが、一応調べたことを載せておきます。
まず、SSR(サーバーサイドレンダリング)とはなにか。
1度は聞いたことがあるかと思いますが、簡単に説明すると、ユーザーのリクエストなしでは Pre-rendering できないページ、最新状態を維持する必要があるページのときにSSRを行うそうです。
イメージしやすいのはECサイトやツイッターのツイートとかですね。
これらは、リクエストを行うごとに毎回ページの内容が変わりますよね。
また、SSRはReactのコンポーネントをHTMLへ変換する前に処理を行うものです。
基本的にはgetServerSideProps
を使ってリクエストを行います。
なので、ページが生成される前に処理を行い、その中で読み込みが終えていないもの(今回でいうとnavigator)を読み込もうとするとエラーが出るわけです。
当然っちゃ当然ですよね。
ReactでもuseEffect
を使わずにマウントされる前にwindow.addEventListener
とか行うとエラーが出ます。
これも同様で、ページを読み込む前にwindow
を指定すると当然window
なんて無いですよ!とエラーが出ます。
これをdynamic
はページを読み込みつつ、コンポーネントを呼んでくれる魔法のメソッドなわけです。
動的に読み込んでくれるおかげで依存関係を解消してくれる。
現にdynamic
を使ってインポートしたコンポーネントは、一足遅れてレンダリングされと思います。
また、{ssr: false}
として指定しているのはSSRの説明を見た方なら当然わかりますよね。
こんな感じでまたNext.jsとReactへの理解が深まりました。
こうしてみるとNext.jsってかなり作りこまれているなと思いました。
便利な反面、最初のうちはエラーの理由が分からなかったりするのですが、そこはやりながら理解していくというのが良いと思います。
なにかご不明な点であったり間違っていることなどがあれば、ぜひコメントにて教えていただけると幸いです。
引き続き勉強に励みます。
皆さんもよきNext.jsライフを!
以上、「Next.jsで「navigator is not defined」が出たときの対処法とSSRの説明」でした!
Thnak you for reading
参考記事
・SSG と SSR で理解する Next.js のページレンダリング
・next.jsでSSRの問題が起きたときにはdynamicとssr:falseでお手頃SSR回避出来る