redirect
redirect
函數允許您將使用者重新導向至另一個 URL。redirect
可用於伺服器組件 (Server Components)、路由處理器 (Route Handlers) 和伺服器操作 (Server Actions)。
在串流上下文 (streaming context)中使用時,會插入一個 meta 標籤以在客戶端觸發重新導向。在伺服器操作中使用時,會向呼叫方返回 303 HTTP 重新導向回應。其他情況下則會返回 307 HTTP 重新導向回應。
如果資源不存在,您可以使用 notFound
函數替代。
參考
參數
redirect
函數接受兩個參數:
redirect(path, type)
參數 | 類型 | 描述 |
---|---|---|
path | string | 要重新導向的 URL,可以是相對或絕對路徑。 |
type | 'replace' (預設) 或 'push' (在 Server Actions 中預設) | 重新導向的類型。 |
預設情況下,redirect
在伺服器操作 (Server Actions) 中會使用 push
(在瀏覽器歷史堆疊中添加新項目),在其他地方則使用 replace
(替換瀏覽器歷史堆疊中的當前 URL)。您可以通過指定 type
參數來覆蓋此行為。
type
參數在伺服器組件中使用時無效。
返回值
redirect
不返回任何值。
行為
- 在伺服器操作和路由處理器中,
redirect
應在try/catch
區塊之後呼叫。 - 如果您希望返回 308 (永久) HTTP 重新導向而非 307 (臨時),可以使用
permanentRedirect
函數。 redirect
內部會拋出錯誤,因此應在try/catch
區塊外呼叫。redirect
可以在客戶端組件的渲染過程中使用,但不能在事件處理程序中使用。您可以使用useRouter
鉤子替代。redirect
也接受絕對 URL,可用於重新導向至外部連結。- 如果您希望在渲染過程之前進行重新導向,請使用
next.config.js
或中介軟體 (Middleware)。
範例
伺服器組件
呼叫 redirect()
函數會拋出 NEXT_REDIRECT
錯誤並終止該路由區段的渲染。
import { redirect } from 'next/navigation'
async function fetchTeam(id: string) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
export default async function Profile({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
const team = await fetchTeam(id)
if (!team) {
redirect('/login')
}
// ...
}
import { redirect } from 'next/navigation'
async function fetchTeam(id) {
const res = await fetch('https://...')
if (!res.ok) return undefined
return res.json()
}
export default async function Profile({ params }) {
const { id } = await params
const team = await fetchTeam(id)
if (!team) {
redirect('/login')
}
// ...
}
須知:
redirect
不需要使用return redirect()
,因為它使用了 TypeScript 的never
類型。
客戶端組件
redirect
可以直接在客戶端組件中使用。
'use client'
import { redirect, usePathname } from 'next/navigation'
export function ClientRedirect() {
const pathname = usePathname()
if (pathname.startsWith('/admin') && !pathname.includes('/login')) {
redirect('/admin/login')
}
return <div>Login Page</div>
}
'use client'
import { redirect, usePathname } from 'next/navigation'
export function ClientRedirect() {
const pathname = usePathname()
if (pathname.startsWith('/admin') && !pathname.includes('/login')) {
redirect('/admin/login')
}
return <div>Login Page</div>
}
須知:在伺服器端渲染 (SSR) 的初始頁面載入時,在客戶端組件中使用
redirect
會執行伺服器端重新導向。
redirect
可以通過伺服器操作在客戶端組件中使用。如果需要使用事件處理程序來重新導向使用者,可以使用 useRouter
鉤子。
'use client'
import { navigate } from './actions'
export function ClientRedirect() {
return (
<form action={navigate}>
<input type="text" name="id" />
<button>Submit</button>
</form>
)
}
'use client'
import { navigate } from './actions'
export function ClientRedirect() {
return (
<form action={navigate}>
<input type="text" name="id" />
<button>Submit</button>
</form>
)
}
'use server'
import { redirect } from 'next/navigation'
export async function navigate(data: FormData) {
redirect(`/posts/${data.get('id')}`)
}
'use server'
import { redirect } from 'next/navigation'
export async function navigate(data) {
redirect(`/posts/${data.get('id')}`)
}
常見問題
為什麼 redirect
使用 307 和 308?
使用 redirect()
時,您可能會注意到使用的狀態碼是 307
表示臨時重新導向,308
表示永久重新導向。傳統上,302
用於臨時重新導向,301
用於永久重新導向,但許多瀏覽器在使用 302
時會將重新導向的請求方法從 POST
更改為 GET
,無論原始請求方法是什麼。
以下面的例子為例,從 /users
重新導向到 /people
,如果您向 /users
發送 POST
請求以創建新使用者,並遵循 302
臨時重新導向,請求方法將從 POST
更改為 GET
。這不合理,因為創建新使用者應向 /people
發送 POST
請求,而不是 GET
請求。
引入 307
狀態碼意味著請求方法會保留為 POST
。
302
- 臨時重新導向,會將請求方法從POST
更改為GET
307
- 臨時重新導向,會保留請求方法為POST
redirect()
方法預設使用 307
而非 302
臨時重新導向,這意味著您的請求將始終保留為 POST
請求。
了解更多關於 HTTP 重新導向的資訊。
版本歷史
版本 | 變更 |
---|---|
v13.0.0 | 引入 redirect 。 |