本サイトはプロモーションが含まれています

Next.js (App Router) のredirect関数でリダイレクトできない場合の対処法

導入

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つあります。

  1. redirect関数を使用し、実装を工夫する
  2. 別のリダイレクト方法を用いる

公式ドキュメントでは、サーバーコンポーネントの場合redirect関数を用いるのを推奨しているため、実装を工夫して対応するのが良いと思います。
クライアントコンポーネントの場合は、next/navigationuseRouterを用いる方法もあるので、そちらの方を使用するのも一つの手です。

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についてもう少し詳しく知りたいと思った方は、以下の講座もおすすめなのでチェックしてみてください!