⛳
[Next.js]router.queryから初回のundefinedを消し去る方法
Next.jsの初回queryのundefined現象
- src/pages/[q].tsx
import { useRouter } from 'next/router'
import React from 'react'
const Page = () => {
const router = useRouter()
const q = router.query['q']
console.log("q:",q)
return <div>{q}</div>
}
export default Page
- 実行結果
console.logの結果
q: undefined
q: query
出力されたHTML
<div></div>
素直にプログラムを組むと、初回はundefinedになっており、SSR後のHTMLも空になっています。
一瞬で解決してみる
この現象の解決方法を検索すると、undefinedの時はいったんnullを戻したり、実処理をuseEffect後にするとかいう解決策が示されています。
実はもっと簡単に直すことが出来ます。
以下のファイルを設置してください。
- src/pages/_app.tsx
import App from 'next/app'
App.getInitialProps = async () => ({ pageProps: {} })
export default App
以上です。
解決後の動作
console.logの結果
q: query
出力されたHTML
<div>query</div>
ということでundefinedは消え去り、SSRもきっちりqueryのデータを受け取った上で行われます。
何故解決するのか
getInitialPropsを入れると、Appコンポーネントのpropsにqueryが送られるようになります。
これが入っていない場合はクライアントでqueryを作り直すので、stateの入れ替えのワンクッションの結果undefinedになります。
デフォルトでqueryを渡さないのは何か事情があるのかもしれませんが、とにかくこれで解決です。
Discussion
_app.tsx
にgetInitialProps()入れてしまうと、全てのページがSSRになってしまうのでよくないのでは?と思いました。router.isReady
を使って制御した方が良いかと。この内容は初回のundefinedを消す方法であって、良い悪いという話が出てくるのは意図がよく分かりません。
用途によってqueryを巻き込んでSSRされたくない場合があるのならもちろん組み方を考えるべきですが、あくまで用途の問題であって良い悪いという話ではありません。
なお、Next.jsはgetInitialProps()の有無に関わりなく、もともと全てのページがSSRされます。