1

I am using ReactRouter v6 and running into a scenario where some pages require shared parent components but some others not, here is an example of my application (URL to component name):

  • /: <UserCenter />
  • /dashboard: <Dashboard />
  • /profile: <Profile />
  • /login: <SignIn />
  • /logout: <SignOut />
  • *: <NotFoundPage />

The former 3 pages (/, /dashboard and /profile) share multiple common parent components like sidebar, footer, title bar, etc. after a successful login, while the rest 3 (/login, /logout and not found) are full screen pages without parent dependents.

I would like to know how I can organize routes to wrap them programmatically under different parent components, and be able to access them at the same time (because I need to enable navigation, for example, auto redirect to / if a login user is accessing /login path)? Thanks!

A pseudo example to what I would like to achieve:

const Routing = (
    <div>
        // Render these 3 pages in routes directly
        <Routes>
            <Route path='/login' element={<SignIn />}
            <Route path='/logout' element={<SignOut />}
            <Route path='*' element={<NotFoundPage />}
        </Routes>

        // Render these 3 pages with parent components
        <Header>
            <Sidebar>
                <Routes>
                    <Route path='/' element={<UserCenter />}
                    <Route path='/dashboard' element={<Dashboard />}
                    <Route path='/profile' element={<Profile />}
                </Routes>
            </Sidebar>
        </Header>
    </div>
);

const APP = () => {
    return (
        <BrowserRouter>
            <Routing />
        </BrowserRouter>
    )
}
Lin Du
  • 88,126
  • 95
  • 281
  • 483
nonemaw
  • 619
  • 1
  • 7
  • 16

1 Answers1

1

You can use layout route

Omitting the path makes this route a "layout route". It participates in UI nesting, but it does not add any segments to the URL.

<UserCenter/>, <Dashboard/> and <Profile/> components will be rendered by <Outlet> inside <Layout/> component.

<SignIn/>, <SignOut/> and <NotFound/> component will be rendered in <App/> component directly.

App.tsx:

import { Outlet, Routes, Route } from "react-router-dom";

function Layout() {
    return (
        <div>
            <header>header</header>
            <aside>sidebar</aside>
            <Outlet />
        </div>
    );
}

export default function App() {
    return (
        <div className="App">
            <Routes>
                <Route element={<Layout />}>
                    <Route path="/" element={<div>user center</div>} />
                    <Route path="/dashboard" element={<div>dashboard</div>} />
                    <Route path="/profile" element={<div>profile</div>} />
                </Route>
                <Route path="/login" element={<div>sign in</div>} />
                <Route path="/logout" element={<div>sign out</div>} />
                <Route path="*" element={<div>not found</div>} />
            </Routes>
        </div>
    );
}

index.tsx:

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { BrowserRouter } from "react-router-dom";

const rootElement = document.getElementById("root")!;
const root = ReactDOM.createRoot(rootElement);

root.render(
    <React.StrictMode>
        <BrowserRouter>
            <App />
        </BrowserRouter>
    </React.StrictMode>,
);

codesandbox

package versions:

  • react-router-dom: 6.10.0
  • react: 18.2.0
  • react-dom: 18.2.0
Lin Du
  • 88,126
  • 95
  • 281
  • 483