Menu

redirect

redirect 函数允许你将用户重定向到另一个 URL。redirect 可以在 Server ComponentsRoute HandlersServer Actions 中使用。

流式传输上下文中使用时,这将插入一个 meta 标签以在客户端执行重定向。在 server action 中使用时,它将向调用者提供一个 303 HTTP 重定向响应。否则,它将向调用者提供一个 307 HTTP 重定向响应。

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

值得注意的是

  • 在 Server Actions 和 Route Handlers 中,redirect 应该在 try/catch 块之后调用。
  • 如果你希望返回 308(永久)HTTP 重定向而不是 307(临时),你可以使用 permanentRedirect 函数

参数

redirect 函数接受两个参数:

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

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

type 参数在 Server Components 中使用时没有效果。

返回值

redirect 不返回值。

示例

Server Component

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

app/team/[id]/page.tsx
TypeScript
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 类型。

Client Component

redirect 可以直接在 Client Component 中使用。

components/client-redirect.tsx
TypeScript
'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>
}

值得注意的是:在 Client Component 中在服务器端渲染 (SSR) 期间的初始页面加载时使用 redirect 时,它将执行服务器端重定向。

redirect 可以通过 Server Action 在 Client Component 中使用。如果你需要使用事件处理程序来重定向用户,你可以使用 useRouter 钩子。

app/client-redirect.tsx
TypeScript
'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
TypeScript
'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