【Next.js】SSR時にRouteオブジェクトのqueryがundefinedになる際の対処法

環境

  • windows10
  • DockerDesktop for Win 3.5.x
  • node 16.13.1
  • npm 8.1.2
  • React 17.0.1
  • Next.js 12.0.7
  • VsCode
  • gitbash 2.32.0.1

現象

`router.query` returns undefined parameter on first render in Next.js · vercel/next.js · Discussion #11484
When I have the following code and visit /pages/profile/foo, the page gets rendered twice and the first time router.query.user is undefined. In file /pages/prof...
  • 初回レンダリング時、queryオブジェクトが空になる
    query: {}
  • 上により、router.queryがundefinedになる
  • 結果として、Httpリクエストがapi/posts/undefinedとかになり、リソースが見つからず、404になる

 原因

理由は公式に記述されています。

自動静的最適化によって静的に最適化されたページは、ルートパラメータが提供されないままハイドレーションされます。

ハイドレーションの後、Next.jsはアプリケーションの更新をトリガーにして、クエリオブジェクトにルートパラメータを提供します。

  • 初回レンダリング時はルートパラメータが提供されないため
  • Nextjsでは、アプリケーションの更新があるまで、routerは空のオブジェクトのまま(useEffectはcomponentDidMountのタイミングで実行されますが、こちらはアプリケーションの更新には含まれない)

対処法

  • RouterオブジェクトのisReadyというboolean値を使用する
  • isReady属性は、routerが完全に準備できているかどうかを表すフラグ
  • isReadeyフラグを用いることで、useEffect内でHttpリクエストを送る前に、クラアント側でrouterオブジェクトをキャッチして使用できることを保証するようにする
const router = useRouter()

useEffect(() => {
  if (!router.isReady) {
    return
  }

  axios.get(`/api/posts/${router.query.postId}`).then((res) => {
    const posts = res.data
    setPosts(posts)
  })
}, [router])

以上です

タイトルとURLをコピーしました