redirect 重定向函数
redirect
函数允许你将用户重定向到另一个 URL。该函数可用于 服务端组件 (Server Components)、路由处理器 (Route Handlers) 和 服务端操作 (Server Actions)。
在 流式上下文 (streaming context) 中使用时,会插入一个 meta 标签在客户端触发重定向。在服务端操作中使用时,会向调用方返回 303 HTTP 重定向响应。其他情况下会返回 307 HTTP 重定向响应。
如果资源不存在,可以使用 notFound
函数 替代。
参考文档
参数
redirect
函数接受两个参数:
redirect(path, type)
参数 | 类型 | 描述 |
---|---|---|
path | string | 要重定向到的 URL,可以是相对路径或绝对路径。 |
type | 'replace' (默认值)或 'push' (服务端操作中默认) | 指定重定向类型。 |
默认情况下,redirect
在 服务端操作 (Server Actions) 中使用 push
(在浏览器历史记录栈中添加新条目),其他情况下使用 replace
(替换浏览器历史记录栈中的当前 URL)。可以通过指定 type
参数来覆盖此行为。
type
参数在服务端组件中使用时无效。
返回值
redirect
不返回任何值。
行为说明
- 在服务端操作和路由处理器中,
redirect
应在try/catch
块之后调用。 - 如果需要返回 308(永久)HTTP 重定向而非 307(临时),可以使用
permanentRedirect
函数。 redirect
内部会抛出错误,因此应在try/catch
块之外调用。redirect
可以在客户端组件 (Client Components) 的渲染过程中调用,但不能在事件处理程序中调用。事件处理程序应使用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')
}
// ...
}
须知:由于使用了 TypeScript 的
never
类型,redirect
不需要使用return redirect()
。
客户端组件
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 函数。 |