Sags
Sags

Reputation: 47

React Router v6 Protected Routes Dynamic Index Page

I'm trying to create a dynamic "index" page whereby if the user is authenticated, the "/" route shows a dashboard component and if they are not authenticated, the "/" route shows a landing page; effectively having the same path for two different pages.

This is easy enough if I check whether the user is authenticated in the component itself; however, I'm trying to use nested routes.

The goal is: one set of public routes (e.g., "/", "/login", "/signup") and one set of private routes ("/", "/settings", "/profile") -- both of which are nested under the "/" route.

I'm just not sure how to achieve this using react router v6.

My Parent Auth Route is very simple:

import { routeConstants } from '@src/constants';
import { useAuth } from '@src/hooks';
import { Navigate, Outlet } from 'react-router-dom';

const AuthRouter = () => {
  const { user } = useAuth();

  if (!user) {
    return <Navigate to={routeConstants.Routes.LogIn} replace />;
  }

  return <Outlet />;
};

export default AuthRouter;

App.ts

      {/* Private Routes */}
      <Route element={<AuthRouter />}>
        <Route path={RouteConstants.Index} element={<Pages.Home />} />
      </Route>

I just can't seem to render a different "/" page based on auth status using nested routes.

Upvotes: 2

Views: 857

Answers (1)

Drew Reese
Drew Reese

Reputation: 202605

If I understand the issue correctly you are asking how to have a root home page route that conditionally renders one of two components depending on the auth status while protecting several sub-routes. For this you'll use a separate layout route specifically for the root index route that handles the "either or" conditional rendering of the landing or dashboard components. The AuthRoute component will handle protecting the authenticated routes.

Example:

const AuthRoute = () => {
  const { user } = useAuth();

  if (user === undefined) {
    return null;
  }

  return user
    ? <Outlet />
    : <Navigate to="/login" replace />;
};
const AuthOrUnauth = ({ AuthElement, UnauthElement }) => {
  const { user } = useAuth();

  return user ? AuthElement : UnauthElement;
};
<Routes>
  <Route
    index
    element={(
      <AuthOrUnauth
        AuthElement={<Dashboard />}
        UnauthElement={<Landing />}
      />
    )}
  />
  <Route path="/login" element={<Login />} />
  <Route path="/signup" element={<Register />} />
  <Route element={<AuthRoute />}>
    <Route path="/settings" element={<Settings />} />
    <Route path="/profile" element={<Profile />} />
  </Route>
</Routes>

Demo

Edit react-router-v6-protected-routes-dynamic-index-page

Upvotes: 1

Related Questions