2
votes

I want to wrap my whole application so that it is not accessible unless the user is logged in. I managed to redirect the user to the login page if the user is not logged in, however, i still see a flash of the private route before the redirection occurs. How can this be avoided?

1
Yes @AndrewZheng i tried that approach but for some reason, i still see a flash of the private page before it redirects - poca
@poca I always do this with swr which blocks rendering until the condition is met. I get the user authenticated with swr and check if the user exists or not then I redirect - enoch

1 Answers

4
votes

Because NextJS is server-side rendered, you either need to check the authentication with getServerSideProps or display a loading indicator on the front-end before the redirect.

Checking authentication client-side

Create a wrapper component and put it inside your _app.js file. By showing a loading component while the user is still being authenticated, you prevent the private dashboard from showing. And note: because Next.js is server-side rendered, the HTML will always show up before the JS is rehydrated. That means, first paint will always occur before the redirect starts.

import { useRouter } from 'next/router'

export const AuthCheck = (props) => {
  const router = useRouter()
  const user = useUser() // you need to implement this. In this example, undefined means things are still loading, null means user is not signed in, anything truthy means they're signed in

  if (typeof window !== 'undefined' && user === null) router.push('/sign-in')

  if(!user) return <Loading /> // a loading component that prevents the page from rendering
   
  return props.children
}

Then in your _app.js

const MyApp = ({ Component, pageProps }) => {
  return (
    <AuthCheck>
      <Component {...pageProps} />
    </AuthCheck>
  )
}

export default MyApp

Checking authentication server-side

Assuming you already have code setup to check authentication server-side, you can use this pattern. Note: you'll need to add this to every single page. getServerSideProps does not work with _app.js or _document.js

export const getServerSideProps = async () => {
  const isAuthenticated = await checkAuthentication() // you need to implement this

  if (!isAuthenticated) {
    return {
      redirect: { destination: '/sign-in', permanent: false },
    }
  }
}