跳到主要内容

redirect

redirect 函数允许你将用户重定向到另一个 URL。redirect 可以在 服务端组件路由处理器服务端操作 中使用。

流式上下文 中使用时,这将插入一个 meta 标签以在客户端发出重定向。在服务端操作中使用时,它将向调用者提供 303 HTTP 重定向响应。否则,它将向调用者提供 307 HTTP 重定向响应。

如果资源不存在,你可以使用 notFound 函数 代替。

参考

参数

redirect 函数接受两个参数:

redirect(path, type)
参数类型描述
pathstring要重定向到的 URL。可以是相对路径或绝对路径。
type'replace'(默认)或 'push'(服务端操作中默认)要执行的重定向类型。

默认情况下,redirect服务端操作 中使用 push(向浏览器历史堆栈添加新条目),在其他地方使用 replace(替换浏览器历史堆栈中的当前 URL)。你可以通过指定 type 参数来覆盖此行为。

RedirectType 对象包含 type 参数的可用选项。

import { redirect, RedirectType } from 'next/navigation'

redirect('/redirect-to', RedirectType.replace)
// 或
redirect('/redirect-to', RedirectType.push)

type 参数在服务端组件中使用时没有效果。

返回值

redirect 不返回值。

行为

  • 在服务端操作和路由处理器中,使用 try/catch 语句时,redirect 应该在 try外部调用。
  • 如果你希望返回 308(永久)HTTP 重定向而不是 307(临时),可以使用 permanentRedirect 函数 代替。
  • redirect 会抛出错误,因此在使用 try/catch 语句时应该在 try外部调用。
  • redirect 可以在渲染过程中在客户端组件中调用,但不能在事件处理程序中调用。你可以使用 useRouter hook 代替。
  • redirect 也接受绝对 URL,可用于重定向到外部链接。
  • 如果你想在渲染过程之前重定向,请使用 next.config.js中间件

示例

服务端组件

调用 redirect() 函数会抛出 NEXT_REDIRECT 错误并终止抛出它的路由段的渲染。

app/team/[id]/page.tsx
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')
}

// ...
}

提示redirect 不需要你使用 return redirect(),因为它使用 TypeScript never 类型。

客户端组件

redirect 可以直接在客户端组件中使用。

components/client-redirect.tsx
'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 hook。

app/client-redirect.tsx
'use client'

import { navigate } from './actions'

export function ClientRedirect() {
return (
<form action={navigate}>
<input type="text" name="id" />
<button>Submit</button>
</form>
)
}
app/actions.ts
'use server'

import { redirect } from 'next/navigation'

export async function navigate(data: FormData) {
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