Authentication and Conditional Routing in Next.js
A comprehensive guide on how to implement a reusable Auth component for Next.js pages.
Next.js is a popular React.js framework with multiple built-in features (SSR/ page-based routing) that provide ease while developing client-side applications.
Introduction:
Anyone that has used React very well understands its unopinionated nature, but that freedom also provides a vast community to reference to, whenever needed. Next.js has grown as a popular choice for building client-side applications, but finding specific solutions can be very hard sometimes as compared to React.
‘Pages’ in Next.js and basic conditional rendering:
Conditional rendering in React is majorly done using React Router, but using it with Next.js isn’t really an optimal choice looking at how projects are structured in it. In Next.js, a page is a React Component exported from a .js
, .jsx
, .ts
, or .tsx
file in the pages
directory. Each page is associated with a route based on its file name. (ref.)
How I like to structure my components is by wrapping all child components inside a ‘MainContent’ component. This is equivalent to any <div>
or fragment containing all your relevant HTML tags.
Usually, it is this component that is conditionally rendered as:
Authentication:
Authentication in applications however isn’t as simple as just using a local variable. Most commonly an API call is made to the server verifying the user auth status and stored in a global store using redux or context API which allows us to distribute it throughout the application so it can be used in other pages/ components. This also helps us to implement an important principle i.e. Single Source of Truth.
Implementation:
I am assuming you have your global store setup as it is beyond the scope of this article.
1. __app.tsx
Next.js has its top-level component called _app.{js,jsx,ts,tsx}
Since I am using redux, I will be loading the authentication state using loadUser action creator. loadUser will contain any API calls and dispatches in case of redux.
2. Auth/index.tsx
In order to make the UI interactive while the state is loading, we will also use a ‘shouldRenderChildren’ variable that will depend on whatever is returned by one of our handlers and render a <Spinner>
accordingly.
const [shouldRenderChildren, setShouldRenderChildren] = useState<boolean>(false);
We will be implementing the following two handlers in case of routing:
2.1. ensureAuthenticated:
allows render of the component if ‘isAuthenticated’ is true otherwise routes to specified URL
returns (used by shouldRenderChildren): isAuthenticated && !isLoading
return logic: will only render children if all processing is done (loading is false) and user is authenticated
route logic: will only route to provided URL if all processing is done (loading is false) and user is unauthenticated
e.g: pages like feed, settings, profile page require authentication status to be true.
2.2. forwardAuthenticated:
routes to specified URL if ‘isAuthenticated’ is true otherwise allows render of component
returns (used by shouldRenderChildren): !isAuthenticated && !isLoading
return logic: children should only be rendered if user is not authenticated as well as all processing is done (loading is false)
route logic: will only route to provided URL if all processing is done (loading is false) and user is authenticated
e.g: pages like login, register require authentication status to be false.
The updated home page file will look like this:
Auth component requires two props to be passed i.e. redirectUrl (the URL we will use inside redirectHandler) and redirectHandler (which is forwardAuthenticated as it is a page which does not require user to be authenticated). (caution: do not redirect to a page that also uses forwardAuthenticated as it will lead to infinite redirects)
Conclusion:
I hope this guide helps you to effectively implement Auth/ Protected Route component for Next.js
Happy Coding :)
Thanks for reading this article! Don’t forget to clap or leave a comment.