Next.js Redirect from / to another page
Caveat
First, you should asses whether you need client-side redirection (within React), server-side redirection (301 HTTP response) or server-side redirection + authentication (301 HTTP response but also having some logic to check authentication).
This is the most complete answer I could write. But, in most scenarios, you do not need any of this. Just redirect as you would do in any React app. Prefer client-side redirections first. Just using useEffect
+ router.push
, and that's it.
Server-side redirection are tempting, in particular when you want to "secure" private pages, but you should assess whether you really need them. Usually, you don't. They induce unexpected complexity, like managing auth token and refresh token. Instead, you may want to add a gateway server, a reverse proxy or whatever upfront server to your architecture for instance to handle those kind of checks.
Keep in mind that Next.js are just React app, and using Next.js advanced features like SSR comes at a cost that should be justified in your context.
Old Next 9.4 answer
Hi, here is an example component working in all scenarios:
Vulcan next starter withPrivate access
Example usage here
The answer is massive, so sorry if I somehow break SO rules, but I don't want to paste a 180 lines piece of code. There is no easy pattern to handle redirection in Next, if you want to both support SSR and static export.
The following scenarios each need a specific pattern:
- server side rendering: we render the page if allowed, HTTP redirect if not
- static rendering (server-side): we render nothing, but we still include the page into the build
- client side rendering, after a static export: we check client side if the user is auth, and redirect or not. We display nothing (or a loader) during this check or if we are redirecting.
- client side rendering after a client redirect using next/router: same behaviour.
- client side rendering after SSR: we use props passed by getInitialProps to tell if the user is allowed, directly at first render. It's just a bit faster, you avoid a blank flash.
At the time of writing (Next 9.4), you have to use getInitialProps
, not getServerSideProps
, otherwise you lose the ability to do next export
.
Next 9.5 update
As stated by @Arthur in the comments, 9.5 also include the possibilities to setup redirects in next.config.js.
The limitations of this feature are not yet clear to me, but they seem to be global redirections, e.g. when you need to move a page or to allow access only during a limited period.
So they are not meant to handle authentication for instance, because they don't seem to have access to the request context. Again, to be confirmed.
Next 10 new doc update
This solution is specific to redirection depending on authentication.
Authentication patterns are now documented
I am not fond of authenticated from getServerSideProps
, because it's in my opinion quite too late and can be difficult to set up with advanced patterns such as handling refresh token. But that's the official solution.
You may also want to check the approach documented in this ticket based on how Vercel's dashboard works (at the time of writing), that prevents flash of unauthenticated content
Next 10.2 header and cookies based rewrites update
Next 10.2 introduces Rewrites based on headers and cookies.
That's a great way to redirect server-side, based on the presence of an authentication cookie or header.
However, keep in mind that this is not a secure redirection. User can alter their request headers with a false token. You still need a gateway, a reverse proxy or an upfront server to actually check token validity and correctly set the headers.
Edit: note that the URL won't change. A rewrite points an URL to an existing page of your application, without changing the URL => it allows you to have "virtual" URLs.
Example use case: imagine you have a page src/contact.tsx
, that is translated, and i18n redirection setup. You can translate the page name itself ("contact") by rewriting /de/kontact
to /de/contact
.
Next 12 update
Now middlewares gives you full-control on server-side redirects.
However, keep in mind again, that most of the time a client-side redirect and check is just enough.
Old answer (works, but will have a messy static render)
Semi-official example
The with-cookie-auth
examples redirect in getInitialProps
. I am not sure whether it's a valid pattern or not yet, but here's the code:
Profile.getInitialProps = async ctx => {
const { token } = nextCookie(ctx)
const apiUrl = getHost(ctx.req) + '/api/profile'
const redirectOnError = () =>
typeof window !== 'undefined'
? Router.push('/login')
: ctx.res.writeHead(302, { Location: '/login' }).end()
try {
const response = await fetch(apiUrl, {
credentials: 'include',
headers: {
Authorization: JSON.stringify({ token }),
},
})
if (response.ok) {
const js = await response.json()
console.log('js', js)
return js
} else {
// https://github.com/developit/unfetch#caveats
return await redirectOnError()
}
} catch (error) {
// Implementation or Network error
return redirectOnError()
}
}
It handles both server side and client side. The fetch
call is the one that actually get the auth token, you might want to encapsulate this into a separate function.
What I would advise instead
1. Redirect on server-side render (avoid flash during SSR)
This is the most common case. You want to redirect at this point to avoid the initial page flashing on first load.
MyApp.getInitialProps = async appContext => {
const currentUser = await getCurrentUser(); // define this beforehand
const appProps = await App.getInitialProps(appContext);
// check that we are in SSR mode (NOT static and NOT client-side)
if (typeof window === "undefined" && appContext.ctx.res.writeHead) {
if (!currentUser && !isPublicRoute(appContext.router.pathname)) {
appContext.ctx.res.writeHead(302, { Location: "/account/login" });
appContext.ctx.res.end();
}
}
return { ...appProps, currentUser };
};
2. Redirect in componentDidMount (useful when SSR is disabled, eg in static mode)
This is a fallback for client side rendering.
componentDidMount() {
const { currentUser, router } = this.props;
if (!currentUser && !isPublicRoute(router.pathname)) {
Router.push("/account/login");
}
}
I could not avoid flashing the initial page in static mode add this point, because you can't redirect during the static build, but it seems better than the usual approaches. I'll try to edit as I make progress.
Full example is here
Relevant issue, which sadly ends up with a client only answer
New issue I've opened regarding redirecton
Redirect to another page based on form input in Next.js
Ok..
For this you can use useRouter hook provided by the nextjs
first you can import it
import { useRouter } from "next/router";
then you can create it's instance and use it to push the react app to new route
based on the value of the given form input value
Here I am using a react state to go to new route
import {useRouter} from 'next/router'
import {useState} from 'react'
export default function SampleComponent(){
const router = useRouter()
const [route, setRoute] = useState()
const handleSubmit = (e) => {
e.preventDefault()
router.push("someBasePath/" + route)
}
return(
<div>
<h1>Example Form</h1>
<form onSubmit={handleSubmit}>
<input type="text" name='route' onChange={(e)=>{setRoute(e.target.value)}} />
<button type="submit">Submit</button>
</form>
</div>
)
}
I hope you are familial with react and useState hook
I hope it will solve your problem
Reactjs/Nextjs- how to redirect to another page using NextJS
Sample routing code:
import { useRouter } from 'next/router'
function Home() {
const router = useRouter()
const handleClick = e => {
e.preventDefault()
router.push('/some-path')
}
return (
<button type="button" onClick={handleClick}>
Go Somewhere
</button>
)
}
Please see the docs for further details.
redirect all `*` to specific path in nextjs
Unfortunately, nextJs doesn't seems to have a proper way to handle this kind of redirection inside the nextConfig, But if you want to redirect any 404 page to home, what you can do is:
- Create a custom 404 page inside the pages, note that your page must be named as 404
- Add this snippet in the 404 file.
import { useEffect } from 'react'
import { useRouter } from 'next/router'
export default function Custom404() {
const router = useRouter()
useEffect(() => {
router.replace('/')
})
return null
}
With that any not found route should redirect to home page.
See this discussion on github
edit:
One last thing, if you want to handle some kind of logic when a user visit some route and redirect if fail, you can do so with getServerSideProps:
- Add the async function getServerSideProps in the page where you want to handle some kind of logic before render the page:
// Page where you want to handle the logic
// data is the props that comes from getServerSideProps
function Page({ data }) {
// Render data...
}
// This gets called on every request
export async function getServerSideProps() {
// fetch some data from external API
const res = await fetch(`https://someapi/fetchData`)
const data = await res.json()
if(!data) {
// Here we redirect the user to home if get some error at the API
return {
redirect: {
destination: '/',
permanent: false
}
}
}
// Otherwise pass the data to Page as props
return { props: { data } }
}
export default Page
It's just an example but you got the idea, if you want to learn more about this, read the docs here
Next JS Static Site: Redirect specific routes to another site?
Inside the getStaticProps
function, there is an option to return a redirect value. This allows for redirecting to internal and external resources.
You could have the code below saved under pages/stuff.tsx
. When a request is made to /stuff
, they will be redirected.
import { GetStaticProps } from 'next';
export const getStaticProps: GetStaticProps = async () => {
return {
redirect: {
destination: 'http://www.redirectedsite.com/stuff',
permanent: false,
},
};
};
const TestPage = (): JSX.Element => {
return <div></div>;
};
export default TestPage;
Next JS Documentation on getStaticProps
redirect
How can I use Next.js redirects?
This doesn't look possible to me, since in the config we only can have static values, and authtoken will change for every login, UI side redirection must be handled from separate AuthContext like we do with react apps.
Another alternative to above approach
is having one more cookie like 'authorized' and it will have value let say true of false. So we can check for 'authorized' is it has value 'true', next.config is below for the same.
Reference: https://nextjs.org/docs/api-reference/next.config.js/redirects#header-cookie-and-query-matching
{
reactStrictMode: true,
async redirects() {
return [
{
source: '/',
destination: '/login',
permanent: true,
has: [
{
type: 'cookie',
key: 'authorized',
value: 'false',
},
],
},
]
},
}
Related Topics
How to Style a Mouseover on an Image Map Using CSS
Removing Ul Indentation with CSS
How to Escape < and > Inside <Pre> Tags
Why Are Frames Deprecated in HTML
Html/CSS - Best Practice for Preserving White Space on Certain Elements
Html5 Localstorage Size Limit for Subdomains
How to Display Vertical Text in Table Headers with Auto Height/Without Text Overflow
Can You Have Multiline HTML5 Placeholder Text in a <Textarea>
Scroll to a Specific Element Using HTML
How to Apply Two CSS Classes to a Single Element
What Are the Ways to Make an HTML Link Open a Folder
Why Does My "Oninvalid" Attribute Let the Pattern Fail
Size of Font in CSS with Slash
Displaying Unicode Symbols in Html
How to Create Links With 'Target="_Blank"' in Markdown