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 Answers
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 },
}
}
}