reactjsnext.jshigher-order-componentsnext-router

Next.js: How to prevent flash of the Unauthorized route/page prior to redirect when implementing a private route?


Essentially I created a HOC for two pages in my Next.js app (i.e. profile and dashboard) two prevent users from accessing them if they're not authorized.

Example: pages/profile.js

import withAuth from "../components/AuthCheck/index";

function Profile() {
  return (
    <>
      <h1>Profile</h1>
    </>
  )
}


export default withAuth(Profile);

My Auth component/HOC:

import { useRouter } from 'next/router'
import { useUser } from '../../lib/hooks'
import { PageLoader } from '../Loader/index'

const withAuth = Component => {
  const Auth = (props) => {
    const { isError } = useUser(); //My hook which is calling /api/user see if there is a user
    const router = useRouter()


    if (isError === 'Unauthorized') {
      if (typeof window !== 'undefined' && router.pathname === '/profile' || router.pathname === 'dashboard') router.push('/login')

      return <PageLoader />
    }
    return (
      <Component {...props} />
    );

  };

  if (Component.getInitialProps) {
    Auth.getInitialProps = Component.getInitialProps;
  }

  return Auth;
};

export default withAuth;

Now what is happening is if you happen to enter /profile or /dashboard in the browser URL bar, before the redirect you'll see the page for a second i.e. flash.

Any idea why that is happening?


Solution

  • I'd consider making use of getServerSideProps on pages that need to be authed, have a look at getServerSideProps . It'll run server side on a page per request.

    Alternatively, it might make sense (depending on your project setup - especially if you have access to auth state in _app.tsx_) to render the auth component in your _app. More specifically, you could add a protected:true prop to the pages that are behind auth wall (using static props). Then in app you can check if a particular page has protected===true and redirect to auth component if the user isn't authed, for example:

                {pageProps.protected && !user ? (
                    <LoginComponent />
                ) : (
                  <Component {...pageProps} />
                )}