66
29

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.

Next.jsのDynamic Routingでパスパラメータを取得したときにundefinedになるときの対処

Last updated at Posted at 2020-05-30

はじめに

Next.jsのDynamic Routingとは/posts/:idみたいなpathでルーティングしたい場合pages/postsディレクトリ配下に[id].tsxを置くことで実現できる機能です。
idの値を使用してデータをフェッチすると思いますが、1回目のレンダリングではidの値を取得できない問題にハマり悩んだので共有しておきます。

パラメータの取得

パスパラメータはクエリパラメータとしてページに送信され、他のクエリパラメータとマージされます。「はじめに」の例で言うと、idの値は以下のように取得できます。

import { useRouter } from 'next/router'

const Post = () => {
  const router = useRouter()
  const { pid } = router.query

  return <p>Post: {pid}</p>
}

export default Post

実際に使用する場合はこんな感じになるかと思います。

import { useRouter } from 'next/router'

const Post = () => {
  const ref = useRef()
  const router = useRouter()
  const id = router.query.id

  useEffect(() => {
    // ここでidの値を使用してデータをフェッチする 
  }, [ref]);

  // fetchしたデータを表示
  return <p>{hoge}</p>
}

export default Post

ここで最初のレンダリングrouter.query.idはundefinedとなります。

公式のドキュメントでは以下のように書かれています

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

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

なので、再レンダリング時にidを取得できるということになります。

ここでuseEffectでデータをfetchするときにidに値が入っていないのでデータを取得できないし、stateも変化しないので再レンダリングできないという問題が起きました。

解決方法

最初のレンダリングでは、router.asPathとrouter.routeは等しくなります。ですが、パスパラメータがqueryで利用可能になり、router.asPathに反映されたあとはパスは違うのでそれによって検知することができます。


import { useRouter } from 'next/router'

const Post = () => {
  const router = useRouter()
  const [id, setId] = useState<number>()

  // この部分を追加
  useEffect(() => {
    // idがqueryで利用可能になったら処理される
    if (router.asPath !== router.route) {
      setId(Number(router.query.id));
    }
  }, [router]);

  // idが取得されてセットされたら処理される
  useEffect(() => {
    if (id) {
      // ここでidの値を使用してデータをフェッチする 
    }
  }, [id]);

  // fetchしたデータを表示
  return <p>{hoge}</p>
}

export default Post

まとめ

  • Next.jsのDynamic Routingは最初のレンダリングでパスパラメータを取得できない
  • router.asPathを使用して処理することでパスパラメータがqueryで利用可能になったときのイベントを発火させることができる

もし、もっと良い実装方法があればぜひコメントで教えてください

66
29
1

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
66
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?