導入
Next.js 13でApp Routerが導入され、記述方法が色々と変わりました。
その中で、新しいリダイレクトの方法としてredirect関数が導入されました。
しかし、このredirect関数を使用したときにうまくリダイレクトできないケースがあったので、その時の対処法を紹介します。
スポンサードリンク
redirect関数とは
redirect関数はApp Routerで新たに追加されたリダイレクトのための関数で、サーバーコンポーネント、クライアントコンポーネント、サーバーアクションなどで使用することができます。
先日リリースされたNext.js 14でも使えます。
使い方としては簡単で、以下のようにリダイレクトしたい場所で、redirect関数を呼び出すだけです。
import { redirect } from 'next/navigation'
export default async function Sample({ zipcode }) { const res = await fetch( `https://zipcloud.ibsnet.co.jp/api/search?zipcode=${zipcode}` ) const data = await res.json()
if (data.status !== 200) { redirect('/home') }}
うまくリダイレク トできないケース
しかし、redirect関数は以下のような場合は機能しません。
- try~catch文内にredirect関数を記述する場合
- Promiseを返す関数内に記述した場合(async関数やPromise.then内での使用など)
例えば、以下のような場合はNEXT_REDIRECT
エラーが出て、リダイレクトされない現象が起きます。
Error: NEXT_REDIRECT at getRedirectError
'use client'import { redirect } from 'next/navigation'import { useEffect } from 'react'
export default function Sample({ zipcode }) { useEffect(() => { (async () => { const res = await fetch( `https://zipcloud.ibsnet.co.jp/api/search?zipcode=${zipcode}` ) const data = await res.json()
if (data.status !== 200) { redirect('/home') } })(); });
return ( <div> <p>リダイレクト</p> </div> )}
リダイレクトできない原因
redirect関数でリダイレクトできない原因についてですが、Next.jsのredirect関数の内部で例外(エラー)を発生させる実装になっていることが原因のようです。
実際にNext.jsのredirect関数の中身を見てみると、以下のようになっています。
export function redirect( url: string, type: RedirectType = RedirectType.replace): never { throw getRedirectError(url, type, false) // ここで、例外(エラー)を発生させている}
このため、try~catch文やPromiseを返す関数内で使用するとNEXT_REDIRECT
エラーが発生し、処理が止まるという事象が発生しています。
例えば、以下の例ではtryブロック内で例外(エラー)が発生しているため、catch内に処理が移り、リダイレクトされないようです。
'use client'
export default function RedirectErrorSample() { function redirectCheck() { try { console.log('try') redirect('/') // ここで例外(エラー)が発生する } catch(e) { console.log(e.message) // e.messageの値は「NEXT_REDIRECT」 } }
return ( <div> <button onClick={redirectCheck}>リダイレクト</button> </div> )}
スポンサードリンク
対処法
対処法としては、以下の2つあります。
- redirect関数を使用し、実装を工夫する
- 別のリダイレクト方法を用いる
公式ドキュメントでは、サーバーコンポーネントの場合redirect
関数を用いるのを推奨しているため、実装を工夫して対応するのが良いと思います。
クライアントコンポーネントの場合は、next/navigation
のuseRouter
を用いる方法もあるので、そちらの方を使用するのも一つの手です。
1. redirect関数を使用し、実装を工夫する
サーバーコンポーネントの場合は、redirect
関数が推奨されているため、実装を工夫して対応します。
この方法はクライアントコンポーネントでも使用できます。
例えば、以下の例だとリダイレクトするかの判定フラグを用意し、リダイレクトするかの情報を保持しています。
そして、リダイレクトが必要な場合はフラグをtrueにし、exportする関数直下でredirect関数を使うことで、try catch内で使われることを防ぎます。
import { redirect } from 'next/navigation'
export default async function Sample({ zipcode }) { let redirectRequested = false // リダイレクトするかの判定フラグ
try { const res = await fetch( `https://zipcloud.ibsnet.co.jp/api/search?zipcode=${zipcode}` ) const data = await res.json() if (data.status !== 200) { redirectRequested = true // リダイレクトする場合はtrue } } catch(e) { console.log(e.message) }
if (redirectRequested) { redirect('/home') // redirect関数をtry catch文の外で実行する }}
2. 別のリダイレクト方法を用いる
クライアントコンポーネントの場合は、useRouter
を使った方法があります。
Next.jsでApp Routerを使用する場合、next/router
からではなく、next/navigation
からインポートするように変わっているので、注意が必要です。
以下のようにrouter.replace('リダイレクトするURL')
やrouter.push('リダイレクトするURL')
を用いることで、リダイレクトすることが可能です。
'use client' import { useRouter } from 'next/navigation'
export default function RedirectErrorSample() { const router = useRouter()
function redirectCheck() { try { console.log('try') router.replace('/') // ここで、リダイレクト } catch(e) { console.log(e.message) } }
return ( <div> <button onClick={redirectCheck}>リダイレクト</button> </div> )}
スポンサードリンク
まとめ
今回は、Next.jsのApp Routerで使用できるredirect関数がうまく動作しないときの対処法を紹介しました。
Next.jsのApp Routerについてもう少し詳しく知りたいと思った方は 、以下の講座もおすすめなのでチェックしてみてください!