🚅

Next.jsにおけるリダイレクトまとめ

2023/01/17に公開

Next.jsを使用したリダイレクト処理はいくつかの方法があります。
それぞれ特性を述べながら紹介していきます。

環境

"next": "^13.1.1"
"react": "^18.2.0"

useEffectを利用する

React.useEffectを使用する方法です。
実装自体の難易度は比較的簡単と言えます。

ですが公式にもある通り、useEffectはレンダー後に作用するフックです。一瞬画面が見えてしまうという点でUXは下がります。

_app.tsx
import React from 'react'
import { useRouter } from 'next/router'

function MyApp({ Component, pageProps, router }: AppProps) {
  const router = useRouter()

  React.useEffect(() => {
    if (router.asPath === '/xxx') {
      router.push('/ooo')
    }
  }, [router.asPath])

  return <Component {...pageProps} />
}

getInitialProps

getInitialPropsはサーバー上で動作します。
クライアント側のレンダリングがなされる前にリダイレクトが可能です。

_app.tsx
import App, { AppProps, AppContext } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />
}

MyApp.getInitialProps = async (appContext: AppContext) => {
  const appProps = await App.getInitialProps(appContext)
  const {
    ctx,
    router: { asPath },
  } = appContext
  if (asPath === '/xxx') {
    ctx.res?.writeHead(302, {
      Location: '/ooo',
    })
    ctx.res?.end()
    return
  }
  return { ...appProps }
}

getServerSideProps

SSRを利用した方法です。各ページ上で実行されます。
redirectオブジェクトを使用してリダイレクト可能です。

export async function getServerSideProps(context) {
  const res = await fetch('xxx')
  const data = await res.json()

  if (!data) {
    return {
      redirect: {
        destination: '/',
        permanent: false,
      },
    }
  }

  return {
    props: {},
  }
}

middlewareを利用する

Next.js v12からmiddleware機能が導入されました。
middlewareに書いた処理はリクエストが完了する前に実行が可能です。

matcherを指定することで、該当したパスをリダイレクトするようにできます。

middleware.ts
import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'

export function middleware(req: NextRequest) {
  return NextResponse.redirect(new URL('ooo', req.url))
}

export const config = {
  matcher: 'xxx',
}

さいごに

紹介したように、それぞれで実装難度と特性があるため万能ではありません。
ご自身の開発環境に合わせて使用ください。

Discussion