DEV Community

Cover image for Next.js Redirect from / to another page
Mahdi BEN RHOUMA
Mahdi BEN RHOUMA

Posted on Originally published at iloveblogs.blog

Next.js Redirect from / to another page

The symptom is usually one of these:

  • the home page renders and then jumps away
  • auth redirects flicker
  • redirect() works in one file but not another
  • a client-side button redirect gets copy-pasted into server code

The root cause is that Next.js has five redirect tools, and each one is for a different phase of the request.

The shortest correct answer is:

  • use redirect() for request-time server redirects
  • use useRouter().push() in a client event handler
  • use redirects() in next.config.js for static path rules

If / should always redirect, use next.config.js

This is the cleanest answer when the rule is fixed.

// next.config.mjs
const nextConfig = {
  async redirects() {
    return [
      {
        source: '/',
        destination: '/dashboard',
        permanent: false,
      },
    ]
  },
}

export default nextConfig
Enter fullscreen mode Exit fullscreen mode

This happens before rendering, so there is no flash of the home page first.

If / redirects based on auth or data, use redirect()

In the App Router, this is the server-side pattern:

// app/page.tsx
import { redirect } from 'next/navigation'

export default async function HomePage() {
  const isLoggedIn = false

  if (isLoggedIn) {
    redirect('/dashboard')
  }

  redirect('/login')
}
Enter fullscreen mode Exit fullscreen mode

The current Next.js docs say redirect() returns a 307 by default, and returns 303 when used in a Server Action.

If the redirect happens after a button click, use useRouter()

This is for event handlers in client components, not for server rendering.

'use client'

import { useRouter } from 'next/navigation'

export default function GoToDashboardButton() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}
Enter fullscreen mode Exit fullscreen mode

If you do not need imperative navigation, keep using <Link />.

The mistake that causes most bad redirects

People often use the client pattern for a server problem:

// Avoid this for root-route redirect logic
'use client'

import { useEffect } from 'react'
import { useRouter } from 'next/navigation'

export default function Page() {
  const router = useRouter()

  useEffect(() => {
    router.push('/dashboard')
  }, [router])

  return null
}
Enter fullscreen mode Exit fullscreen mode

This works, but it is the wrong tool for a route-level redirect. The user briefly loads /, then navigates away. Search crawlers and users both get a worse experience.

Another easy mistake: calling redirect() inside try

The docs explicitly note that redirect() throws. If you wrap it inside try/catch, you can accidentally swallow the navigation.

Use this shape instead:

import { redirect } from 'next/navigation'

export async function createProject() {
  let id: string

  try {
    id = 'abc123'
  } catch (error) {
    throw error
  }

  redirect(`/projects/${id}`)
}
Enter fullscreen mode Exit fullscreen mode

Which redirect API should you pick?

  • Known path rule for every request: redirects() in next.config.js
  • Request-time condition in server code: redirect()
  • Canonical URL changed permanently: permanentRedirect()
  • Click handler in client UI: useRouter().push()

That mapping is the part most articles skip, and it is why the same redirect can feel broken in three different ways.

For adjacent routing gotchas, keep these open:

References

Related


Originally published at https://www.iloveblogs.blog

Top comments (0)