Sergio Xalambrí
August 20, 2019

# Redirects in Next.js, the Best Way

Learn how to create redirects when using Next.js in the most efficient way.

When working with Next.js is super common to reach the point you need to redirect the user to another page, maybe because the user tried to access a private page or the user tried to access an old page.

This could be done in multiple ways, the most popular is to use an HTTP Redirect to achieve this, or
`Router.replace` if the page is accessed client-side.

While that works just fine is not ideal, for the first render the user will need an extra request to the server to get the correct page, but it turns out you already know the page the user is going to request since you are setting the HTTP Redirect, why not then render the correct page at straightaway?

## Server-Side Code

This way to set the redirect involves both Server and Client-side code, let's start with the server-side code. Let's say we have two pages, a `/login` and a `/private` page, both in our pages directory like this.

- pages
  - login.js
  - private.js

In our private page we want to render our login page if the user is not logged in, let's say we know if the user is logged in because it has a certain cookie. We could validate the logged-in state in `getInitialProps`.

    PrivatePage.getInitialProps = async context => {
      const { sessions } = readCookies(context.req);
      if (!session) return { loggedIn: false };
      // the code required for your private page
    };

> Note: `readCookies` is a fake function that should read the cookies from the request headers and return an object with them.

Now in our `PrivatePage` component, we can render the login directly.

    import dynamic from "next/dynamic";
    const LoginPage = dynamic(() => import("./login"));
    // more imports here

    function PrivatePage({ loggedIn, ...props }) {
      // some hooks here that need to be before the condition
      if (!loggedIn) return <LoginPage />;
      // the JSX the private page will render
    }

    // define getInitialProps here

    export default PrivatePage;

With this when the user access `/private` and doesn't have the `session` cookie, it will instead receive the HTML of the login page.

> Note: We used a dynamic import to avoid loading the code of LoginPage if it's not going to be used. This will save the user a few kB.

## Client-Side Code

Let's go to the Client-Side part of our redirect, the user accessed `/private` and received the login page HTML, that's great but the user still sees `/private` in their browser. Let's fix that.

Next comes with a module called `next/router` which lets us change the route programmatically, we could use that to navigate to another page without requiring the user to click a link.

Let's add an effect in our `PrivatePage` to change the URL.

    // more code here

    function PrivatePage({ loggedIn, ...props }) {
      // some hooks here that need to be before the condition
      React.useEffect(() => {
        if (loggedIn) return; // do nothing if the user is logged in
        Router.replace("/private", "/login", { shallow: true });
      }, [loggedIn]);

      if (!loggedIn) return <LoginPage />;
      // the JSX the private page will render
    }

    // more code here

This effect will do the trick, what that is doing is, first, validate if the user is logged in to do nothing, but if the user is not logged in it will replace the current URL with `/`.

The function `Router.replace` receives the `href` which is the actual route inside Next (aka the page) and the `as` which is the route we want to show to the user. Those two let use tell Next.js to use our already loaded `PrivatePage` but disguise it as `/login` in the browser.

The `shallow: true` tell Next to do not call `getInitialProps`, combine with the other two will make Next only change the URL but not doing anything else, this means technically the user is still on `PrivatePage` which is rendering `LoginPage`.

When the user log in into the application it will be redirected back to `/private` but this time without the `shallow: true` and that will cause the `getInitialProps` to be executed again so it will see this time it has the `session` cookie and it will continue the normal flow of our `PrivatePage`.

## Final Words

This is the best approach to implement redirects using Next, I learned it while I was working at ZEIT the creators of the framework and is how I implemented a few redirects back there.