Next.jsで、サーバー・クライアントで一度だけやりたい処理
たとえば`firebase.initializeApp()`とか、特定のライブラリにSSR時には何もしなくてよいことを伝えるAPIとか。
ドキュメントにもコレだ!という部分がなかったので書いておく。
クライアント
`pages/_app.js`で、`useEffect(fn, [])`でできる。
import React, { useEffect } from "react"; function MyApp({ Component, pageProps }) { useEffect(() => { /* ここでやる */ }, []); return <Component {...pageProps} /> } export default MyApp
という感じ。
この`_app.js`は、`pages`配下のルートのコンテナ的存在で、ドキュメントにも`componentDidCatch()`などに利用しろと書いてあった。
URLが変わってページが切り替わるのはこいつの子であるので、とりあえず一度だけやりたい処理を書く場所としてはわかりよい。
`useEffect()`にすることで、SSR時は実行されないので、クライアントでのみ実行したいことができるといわけ。
必ず子コンポーネントの`useEffect()`よりも先に実行したという場合は、`useEffect()`ではなく、`useLayoutEffect()`にすればよい。(パフォーマンスにはよくない)
サーバー
SSR時のみ実行したい処理を、シュッと書く方法はなさそう。
インターネッツから探しだした情報としては、こうすればSSR時かどうかはわかる、と。
const isSSR = typeof window === "undefined";
なのでおなじく`_app.js`のコンポーネント定義の外あたりに書いておくしかないかな・・という感じ。
import React, { useEffect } from "react"; if (typeof window === "undefined") { /* ここでやる */ } function MyApp({ Component, pageProps }) { return <Component {...pageProps} /> } export default MyApp
2020年にもなってこんな書き方させるってマジ?天下のNextさんが?って思ってたら、それ用のテストまであって本気のご様子だった・・・。
クライアントサイドでのバンドルにも含まれないんですって!!