redirect

Функция redirect позволяет перенаправлять пользователя на другой URL. redirect может использоваться в Серверных компонентах (Server Components), Обработчиках маршрутов (Route Handlers) и Серверных действиях (Server Actions).

При использовании в контексте потоковой передачи (streaming context) функция вставляет мета-тег для выполнения перенаправления на стороне клиента. При использовании в серверном действии она возвращает HTTP-ответ с кодом 303 для перенаправления вызывающей стороне. В остальных случаях возвращается HTTP-ответ с кодом 307.

Если ресурс не существует, вместо этого можно использовать функцию notFound.

Справочник

Параметры

Функция redirect принимает два аргумента:

redirect(path, type)
ПараметрТипОписание
pathstringURL для перенаправления. Может быть относительным или абсолютным.
type'replace' (по умолчанию) или 'push' (по умолчанию в Server Actions)Тип перенаправления.

По умолчанию redirect использует push (добавляет новую запись в стек истории браузера) в Серверных действиях (Server Actions) и replace (заменяет текущий URL в стеке истории браузера) во всех остальных случаях. Это поведение можно переопределить, указав параметр type.

Параметр type не имеет эффекта при использовании в Серверных компонентах.

Возвращаемое значение

Функция redirect не возвращает значения.

Поведение

  • В Серверных действиях и Обработчиках маршрутов redirect должна вызываться после блока try/catch.
  • Если требуется вернуть HTTP-перенаправление с кодом 308 (Постоянное) вместо 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>
}

Важно: При использовании redirect в Клиентском компоненте во время первоначальной загрузки страницы при SSR выполняется серверное перенаправление.

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 для постоянного, многие браузеры изменяли метод запроса при перенаправлении с POST на GET при использовании 302, независимо от исходного метода запроса.

Рассмотрим пример перенаправления с /users на /people. Если сделать POST запрос на /users для создания нового пользователя и получить 302 временное перенаправление, метод запроса изменится с POST на GET. Это нелогично, так как для создания пользователя должен использоваться POST запрос на /people, а не GET.

Введение кода состояния 307 означает, что метод запроса сохраняется как POST.

  • 302 - Временное перенаправление, изменяет метод запроса с POST на GET
  • 307 - Временное перенаправление, сохраняет метод запроса как POST

Метод redirect() по умолчанию использует 307 вместо 302, что означает сохранение POST запросов.

Подробнее о HTTP-перенаправлениях.

История версий

ВерсияИзменения
v13.0.0Добавлена функция redirect.