0

I'm a bit new to two-sided applications (and to React). I'm currently building an application that has both a "user" and a "business" side, and the type of user is decided after the user authenticates themselves. For that, my current approach is to simply create multiple versions of routers, and depending on the redux state for the user's type, I am dynamically loading in a different router. In the case that a user isn't authenticated, I am making use of a "generic" default router. Once the user logs in, the router is then switched to the appropriate one under App.js

I am wondering if there is a better way to do this, particularly because after a user authenticates themselves, there is a significant delay (a couple of seconds) in the router being switched in the background. For example, the route "/" goes to the landing page react component for the "generic" router, but goes to the dashboard page for the "user" router. Once the user logs in, I redirect them to the "/" router to move them to the dashboard page, however there is a weird delay and the user is actually taken back to the landing page for a few seconds, then the page re-builds to the proper user dashboard that is expected at the "/" route for an authenticated user.

Here is the code for the different types of routers:

export function UserRouter() {
  return useRoutes([
    {
      path: '/learn',
      element: <DashboardLayout />,
      children: [
        { path: ':id', element: <Learn />},
      ]
    },
    {
      path: '/dashboard',
      element: <DashboardLayout />,
      children: [
        { path: 'overview', element: <Overview /> },
        { path: 'tasks', element: <Tasks /> },
        { path: 'community', element: <Community /> },
        { path: 'announcements', element: <Announcements /> },
      ],
    },
    { path: '/companies',
      element: <DashboardLayout />,
      children: [
        { path: ':id', element: <Company />},
      ]
    },
    {
      path: '/termDocuments',
      element: <EmptyPage />,
      children: [
        { path: ':embedURL', element: <AirtableEmbedPage />},
      ]
    },
    {
      path: '/',
      element: <LogoOnlyLayout />,
      children: [
        { path: '/', element: <Navigate to="/dashboard/overview" /> },
        { path: 'login', element: <Login /> },
        { path: 'register', element: <UserRegister /> },
        { path: 'landing', element: <Landing />},
        { path: '404', element: <NotFound /> },
        { path: '*', element: <Navigate to="/404" /> },
      ],
    },
    { path: '*', element: <Navigate to="/404" replace /> },
  ]);
}

export function BusinessRouter() {
  return useRoutes([
    {
      path: '/dashboard',
      element: <DashboardLayout />,
      children: [
        { path: 'overview', element: <BusinessOverview /> },
        { path: 'home', element: <BusinessHomePage /> },
        { path: 'community', element: <BusinessCommunity /> },
        { path: 'announcements', element: <BusinessAnnouncements /> },
      ],
    },
    { path: '/companies',
      element: <DashboardLayout />,
      children: [
        { path: ':id', element: <Company />},
      ]
    },
    {
      path: '/termDocuments',
      element: <EmptyPage />,
      children: [
        { path: ':embedURL', element: <AirtableEmbedPage />},
      ]
    },
    {
      path: '/',
      element: <LogoOnlyLayout />,
      children: [
        { path: '/', element: <Navigate to="/dashboard/overview" /> },
        { path: 'login', element: <BusinessLogin /> },
        { path: 'register', element: <UserRegister /> },
        { path: 'landing', element: <Landing />},
        { path: '404', element: <NotFound /> },
        { path: '*', element: <Navigate to="/404" /> },
      ],
    },
    {
      path: '/business',
      element: <DashboardLayout />,
      children: [
        { path: 'app', element: <Overview />}
      ],
    },
    { path: '*', element: <Navigate to="/404" replace /> },
  ]);
}

export function GenericRouter() {
  return useRoutes([
    {
      path: '/',
      element: <LogoOnlyLayout/>,
      children: [
        {path: '/', element: <Landing/>},
        {path: '404', element: <NotFound/>},
        {path: 'founder', element: <Founders/>},
        {path: '*', element: <Navigate to="/"/>},
        // {path: '*', element: <Navigate to="/404"/>},
      ],
    },
    {
      path: '/business',
      element: <LogoOnlyLayout/>,
      children: [
        {path: 'login', element: <BusinessLogin/>},
        {path: 'register', element: <UserRegister/>},
      ],
    },
    {
      path: '/user',
      element: <LogoOnlyLayout/>,
      children: [
        {path: 'login', element: <Login/>},
        {path: 'register', element: <UserRegister/>},
      ],
    },
    {path: '*', element: <Navigate to="/" replace/>},
    // {path: '*', element: <Navigate to="/404" replace/>},
  ]);
}

And here is the actual switching of the router based off of a redux variable that is updated in the background (within App.js)

const selectRouter = (userType) => {
    switch (userType) {
        case USER:
            return <UserRouter/>
        case BUSINESS:
            return <BusinessRouter/>
        default:
            return <GenericRouter/>
    }
}

function RouterChoice() {
    const userType = useSelector(state => state.auth?.userType)
    return selectRouter(userType)
}

export default function App() {
    return (
        <StylesProvider injectFirst>
            <ThemeProvider>
              <ScrollToTop />
                <BaseOptionChartStyle />
                <RouterChoice />
            </ThemeProvider>
        </StylesProvider>
    );
}
Kkrockera
  • 1
  • 2
  • You *could* create route protection that looks at the `userType` value but I think your issue is more along the lines of not providing any sort of "loading" indicator that authentication is processing and that this is why it seems like the UI is "stuck" or delayed in responding. It sounds like you are immediately navigating and then seconds later the *actual* auth state is set and the UI "catches up". – Drew Reese Jul 30 '22 at 07:01
  • Gotcha, so I was thinking of having an intermediary "/success" route which links to a page that indicates the dashboard is loading. Mostly wanted to check if there was a better practice to this (such as within every sub-page navigating a user away depending on whether they are logged in as a business or a user or unauthenticated). I looked into route protection and it makes sense - I am wondering in general what the best practice is for when a user goes to a route they don't belong at (ex - an "/analytics" route which a user for some reason manually types into their browser). Thanks! – Kkrockera Jul 30 '22 at 18:43
  • Does this help answer that follow-on question? https://stackoverflow.com/a/66289280/8690857 – Drew Reese Jul 31 '22 at 02:17

0 Answers0