skip to Main Content

I have a react app with 2 different layouts, "main layout" and "auth layout". I found the my main layout pages work no problem but it doesn’t appear to load the auth layout pages. If I try and visit "/login", I get a blank main layout page which makes me think it’s only hitting the first <Route> section.

<div className="App">
  <Provider store={store}>
    <BrowserRouter>
      <Switch>
        <Route>
          <MainLayout>
            <Switch>
              <Route path="/" exact component={Dashboard} />
              <Route path="/search" exact component={SearchResults} />
              <Route path="/user/:user_id" exact component={Profile} />
              <PrivateRoute path="/settings" exact component={Settings} />
              <Route
                path="/communities"
                exact
                component={CommunityDashboard}
              />
              <PrivateRoute
                path="/communities/new"
                exact
                component={CommunityNew}
              />
              <Route
                path="/communities/view/:community_id"
                exact
                component={CommunityView}
              />
              <PrivateRoute
                path="/communities/edit/:community_id"
                exact
                component={CommunityEdit}
              />
              <Route path='/404' component={Error404} />
            </Switch>
          </MainLayout>
        </Route>
        <Route>
          <AuthLayout>
            <Switch>
              <Route
                path="/password-reset/:reset_key?"
                exact
                component={PasswordReset}
              />
              <Route path="/register" exact component={Register} />
              <Route path="/login" exact component={Login} />
            </Switch>
          </AuthLayout>
        </Route>

        <Redirect from='*' to='/404' />
      </Switch>
    </BrowserRouter>
  </Provider>
</div>

I understand that Switch will render the first <Route> that matches and is probably why my setup isn’t working. How can I render both layouts without messing with the paths I’ve already made?

2

Answers


  1. To ensure proper rendering of the AuthLayout for authentication-related routes ("/password-reset", "/register", "/login"), you might need to restructure your routes. Here’s an example of how you could modify the route configuration:

    <div className="App">
    <Provider store={store}>
        <BrowserRouter>
            <Switch>
                <Route path="/password-reset/:reset_key?" exact>
                    <AuthLayout>
                        <PasswordReset />
                    </AuthLayout>
                </Route>
                <Route path="/register" exact>
                    <AuthLayout>
                        <Register />
                    </AuthLayout>
                </Route>
                <Route path="/login" exact>
                    <AuthLayout>
                        <Login />
                    </AuthLayout>
                </Route>
                {/* Other MainLayout routes */}
                <Route>
                    <MainLayout>
                        <Switch>
                            <Route path="/" exact component={Dashboard} />
                            <Route path="/search" exact component={SearchResults} />
                            <Route path="/user/:user_id" exact component={Profile} />
                            <PrivateRoute path="/settings" exact component={Settings} />
                            <Route path="/communities" exact component={CommunityDashboard} />
                            <PrivateRoute path="/communities/new" exact component={CommunityNew} />
                            <Route path="/communities/view/:community_id" exact component={CommunityView} />
                            <PrivateRoute path="/communities/edit/:community_id" exact component={CommunityEdit} />
                            <Route path='/404' component={Error404} />
                        </Switch>
                    </MainLayout>
                </Route>
                <Redirect from='*' to='/404' />
            </Switch>
        </BrowserRouter>
    </Provider>
    

    By nesting the specific routes within their respective layouts (AuthLayout for authentication-related routes and MainLayout for the rest), you can ensure that the correct layout gets applied to the corresponding routes.

    Ensure that AuthLayout and MainLayout are components properly defining their layout structure and handling the rendering of children components accordingly. This structure should help in rendering the appropriate layout for different sets of routes in your React app.

    Login or Signup to reply.
  2. I sort of addressed this in your other post here. The issue with your initial code is that the Switch component renders the first child Route or Redirect that matches the location, which is the first pathless Route rendering the MainLayout… the second Route rendering the AuthLayout is unreachable.

    To fix this you can provide a route path to the "layout routes" such that they participate in route matching more exclusively. Keep in mind also that in React-Router-DOM v5 and the Switch component that route path order and specificity matters, order the routes in the inverse order of path specificity, e.g. more specific paths before less specific paths. This should remove the need to specify the exact prop in nearly 100% of use cases.

    Example:

    <div className="App">
      <Provider store={store}>
        <BrowserRouter>
          <Switch>
            <Route
              // match only these path prefixes
              path={["/password-reset/:reset_key?", "/register", "/login"]}
            >
              <AuthLayout>
                <Switch>
                  <Route
                    path="/password-reset/:reset_key?"
                    component={PasswordReset}
                  />
                  <Route path="/register" component={Register} />
                  <Route path="/login" component={Login} />
                </Switch>
              </AuthLayout>
            </Route>
    
            {/* Match all other paths */}
            <Route>
              <MainLayout>
                <Switch>
                  <Route path="/search" component={SearchResults} />
                  <Route path="/user/:user_id" component={Profile} />
                  <PrivateRoute path="/settings" component={Settings} />
    
                  {/* communities paths, decreasing specificity */}
                  <Route
                    path="/communities/view/:community_id"
                    component={CommunityView}
                  />
                  <PrivateRoute
                    path="/communities/edit/:community_id"
                    component={CommunityEdit}
                  />
                  <PrivateRoute path="/communities/new" component={CommunityNew} />
                  <Route path="/communities" component={CommunityDashboard} />
    
                  <Route path='/404' component={Error404} />
    
                  {/* Exactly match home path before catch-all redirect */}}
                  <Route path="/" exact component={Dashboard} />
    
                  <Redirect from='*' to='/404' />
                </Switch>
              </MainLayout>
            </Route>
          </Switch>
        </BrowserRouter>
      </Provider>
    </div>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search