Movatterモバイル変換


[0]ホーム

URL:


terrierscriptterrierscript
🍃

nextjsのISRを使うときのfallback指定について理解するまでの話

に公開

next.jsのISRを使おうとして「なんか全然うまく行かない」ってなってたのがやっと理解出来たのでメモ

問題編

とりあえず見様見真似でISRはrevalidateとfallbackつければ良いんだな?とやってみたところ、どうもpropsが空Objectになってしまうようで悩んでいた。

例えば下記のような場合、エラーが起きる

// pages/greeting/[name].jsconstPage=(props)=>{// ↓ここでエラーreturn<div>Hello{props.name.toUpperCase()}</div>}exportconstgetStaticProps=async(req)=>{return{props:{name: req.params.name},revalidate:100}}exportconstgetStaticPaths=async(req)=>{return{paths:[],fallback:true}}exportdefaultPage
TypeError: Cannot read property 'toUpperCase' of undefined   9 |   // }  10 | > 11 |   return <div>Hello {props.name.toUpperCase()}</div>     |                                ^  12 | }

ここからよくよく調べたりドキュメントを読んだりしているとどうやらこれだけでは駄目らしいということがわかってきた。

解決編

まずfallback: trueの挙動として文字通り「fallback向けページ」を生成する。
fallbackページというのがはっきりしなかったが、これが「propsが空Object状態のページ」ということらしい。
このあとgetStaticPropsを呼び出し、そのJSONを当てはめた状態で再レンダリングするようだ。

TypeScriptで表せば、こういう違いになるだろう

// 通常のSSRの場合constPage:FC<{ foo:string, baz:string}>//`fallback:true`にした場合constPage:FC<{ foo:string, baz:string}|{}>

ここから解決策を見ていく

解決策A: fallback: "blocking"を指定する

これは簡素。fallback: "blocking"にすればよい。

exportconstgetStaticPaths:GetStaticPaths=async(req)=>{return{paths:[],fallback:"blocking"}}

必ず先にビルドが走るので、propsが入っている状態になる

解決策B:fallback: trueにしたままrouter.isFallbackの判定を入れる

fallback: trueでのパフォーマンスを維持したいなら、下記のようにrouter.isFallbackを利用する。

import{ useRouter}from"next/router"constPage=(props)=>{const router=useRouter()if(router.isFallback){return<div>Loading...</div>}return<div>Hello{props.name.toUpperCase()}</div>}

こうするとまずisFallback=trueの状態で空オブジェクトになり、その後getStaticPropsを取得する処理が走る。

備考:next devではISRの検証は出来ない

In development (next dev), getStaticProps will be called on every request.

とのことで、devモードでは毎回getStaticPropsが呼び出される模様

バッジを贈って著者を応援しよう

バッジを受け取った著者にはZennから現金やAmazonギフトカードが還元されます。


[8]ページ先頭

©2009-2025 Movatter.jp