Max Schmitt

October 1 2020

Next.js: How to Redirect from getInitialProps

In a Next.js app, you might want to redirect during the execution of getInitialProps(). For example, if somebody is trying to access a members-only page but is not logged in (by the way, make sure you're authenticating your users securely).

Client-Side vs. Server-Side Redirects in Next.js

Redirects in Next.js work more or less as you would expect them to. We only need to keep in mind that we have two ways of redirecting the user:

  • Client-side redirects – If the user is accessing a page during client-side navigation, we'll use the Next.js' Router object to redirect him
  • Server-side redirects – If the user is accessing a page during server-side Rendering (SSR), we'll redirect via the appropriate HTTP response

Code example

Here's what this might look like in code:

pages/members-only.js

import Router from 'next/router'
async function getInitialProps({ res, user }) {
if (!user) {
if (res) {
// On the server, we'll use an HTTP response to
// redirect with the status code of our choice.
// 307 is for temporary redirects.
res.writeHead(307, { Location: '/' })
res.end()
} else {
// On the client, we'll use the Router-object
// from the 'next/router' module.
Router.replace('/')
}
// Return an empty object,
// otherwise Next.js will throw an error
return {}
}
return { secretData: '...' }
}
function MembersOnlyPage({ secretData }) {
return (
<p>
You should never see this if you're not logged in:
{secretData}
</p>
)
}
MembersOnlyPage.getInitialProps = getInitialProps
export default MembersOnlyPage

External Client-Side Redirects without Content Flashing in Next.js

If you want to do a client-side redirect to an external page, you can use window.location and a never-resolving promise to make sure that nothing gets rendered while the redirect is taking place.

pages/flamingo.js

async function getInitialProps({ res, user }) {
const targetURL = 'https://www.youtube.com/watch?v=11KaKhGAa3I' // 🦩
if (res) {
// On the server, we'll use an HTTP response to
// redirect with the status code of our choice.
// 307 is for temporary redirects.
res.writeHead(307, { Location: targetURL })
res.end()
} else {
// We'll redirect to the external page using
// `window.location`.
window.location = targetURL
// While the page is loading, code execution will
// continue, so we'll await a never-resolving
// promise to make sure our page never
// gets rendered.
await new Promise((resolve) => {})
}
return {}
}
function FlamingoPage() {
return <p>This should never get rendered</p>
}
FlamingoPage.getInitialProps = getInitialProps
export default FlamingoPage