How to Render Components with Different Layouts/Elements Using React-Router-Dom V6

How do I render components with different layouts/elements using react-router-dom v6

If I understand your question, you are wanting to render the nav and sidebar on the non-login route. For this you can create a layout component that renders them and an outlet for the nested routes.

Using nested routes

import { Outlet } from 'react-router-dom';

const AppLayout = () => (
<>
<NavBar />
<SideBar />
<main className={styles["main--container"]}>
<div className={styles["main--content"]}>
<Outlet /> // <-- nested routes rendered here
</div>
</main>
</>
);

const App = () => {
return (
<>
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route element={<AppLayout />} >
<Route path="/" element={<Dashboard />} /> // <-- nested routes
</Route>
</Routes>
</>
);
};

Using a routes configuration and useRoutes hook

const routesConfig = [
{
path: "/login",
element: <LoginPage />,
},
{
element: <AppLayout />,
children: [
{
path: "/",
element: <Dashboard />,
},
],
},
];

...

import { useRoutes } from 'react-router-dom';

const App = () => {
const routes = useRoutes(routesConfig);

return routes;
};

Using a routes configuration and data routers (introduced in v6.4.0)

const routesConfig = [
{
path: "/login",
element: <LoginPage />,
},
{
element: <AppLayout />,
children: [
{
path: "/",
element: <Dashboard />,
},
],
},
];

...

import { createBrowserRouter, RouterProvider } from 'react-router-dom';

const router = createBrowserRouter(routesConfig);

const App = () => {
return <RouterProvider router={router} />;
};

React Router v6 : How to render multiple component inside and outside a div with the same path

Part of the issue is that you are rendering multiple identical paths, i.e. two "/" paths and two nested index paths. This won't work.

In react-router-dom v6 you can create what are called layout components. The layout components can render your headers and footers, sidebars, drawers, and general content layout elements, and importantly an Outlet component for the nested/wrapped Route components to be rendered into.

Example:

import { Outlet } from 'react-router-dom';

const AppLayout = ({ admin }) => admin ? (
<>
<Topbar />
<div className="container">
<Sidebar />
<Outlet />
</div>
</>
) : null;

Render the layout component into a Route wrapping the routes you want to be rendered into the specific layout.

<Routes>
<Route path="/login" element={<Login/>} />
<Route element={<AppLayout admin={admin} />}>
<Route index element={<Home />} />
<Route path="/users" element={<UserList />} />
<Route path="/user/:userId" element={<User />} />
<Route path="/newUser" element={<NewUser />} />
<Route path="/productList" element={<ProductList />} />
<Route path="/product/:productId" element={<Product />} />
<Route path="/newProduct" element={<NewProduct />} />
</Route>
</Routes>

Page layout broken in React Router v6

Layout should render an Outlet for the children Routes to be rendered into.

import { Outlet } from 'react-router-dom';

function Layout() {
return (
<div className="layout">
<Header />
<SidePanel />
<div className="main" style={{ marginTop: "100px" }}>
<Outlet />
</div>
</div>
);
}

Outlet

An <Outlet> should be used in parent route elements to render their
child route elements. This allows nested UI to show up when child
routes are rendered.

React Router v6 shared layouts

you have to render an <Outlet /> for inside your layout element to specify where the active child route should be mounted.

<Routes>
<Route path="/" element={<p>Home</p>} />
<Route element={<div style={{ background: 'red' }} > <Outlet /> </div>}>
<Route path="/login" element={<p>Login</p>} />
</Route>
</Routes>

How to implement multiple route with single container or layout in react-router-dom v6

If you've "common" layout containers you want to share/render with multiple routes/routed components then it's common to have each layout render nested routes into an Outlet component.

Example:

import { Outlet } from 'react-router-dom';

const LoginLayout = () => (
<div /* layout props & styling */ >
{/* local layout UI */}
<Outlet /> // <-- nested routes rendered here
</div>
);

const AdminLayout = () => (
<div /* layout props & styling */ >
{/* local layout UI */}
<Outlet />
</div>
);

...

<Routes>
<Route element={<LoginLayout />}>
<Route path="/" element={<SignInForm />} />
<Route path="/signin" element={<SignInForm />} />
<Route path="/newpassword" element={<NewPassword />} />
<Route path="/phoneverification" element={<PhoneVerification />} />
<Route path="/continuewithphone" element={<ContWithPhone />} />
<Route path="/resetpassword" element={<ResetPassword />} />
<Route
path="/confirm-resetpassword"
element={<ConfirmResetPassword />}
/>
</Route>
<Route element={<AdminLayout />}>
// Routes here
</Route>
</Routes>

react-router v6 double rendering components

The GalleryCard and About components are rendered twice because they are rendered in two places.

index

<Routes>
<Route path="/" element={<App />}>
<Route path="/about" element={<About />} /> // <-- here
<Route path="/gallery" element={<Gallery />} /> // <-- here
</Route>
</Routes>

App

const App = () => {
const background = require("../../assets/images/45-degree-fabric-light.png")

return (
<div className="App">
<div className='background'>
<img src={background} className='background' alt="background" />
</div>
<NavBar/>
<Divider className='divider' textAlign="left">GALLERY</Divider>
<div className='card-container'>
<GalleryCard/> // <-- and here
</div>
<Divider className='divider' textAlign="left">ABOUT</Divider>
<About/> // <-- and here
</div>
);
}

Remove them from App, replace them with an Outlet component so the nested routes render out there in their place.

import { Outlet } from 'react-router-dom';

...

const App = () => {
const background = require("../../assets/images/45-degree-fabric-light.png")

return (
<div className="App">
<div className='background'>
<img src={background} className='background' alt="background" />
</div>
<NavBar/>
<Outlet />
</div>
);
}

Move the divider and title to the components.

React Router Dom, render a component only for some routes

Quick Solution:

You could simply do like below, adding the Nav where you want. I'm not sure if you can know the path in App, since it's not wrapped inside the Router.

import { BrowserRouter as Router, Routes, Route, matchPath } from "react-router-dom";
import Nav from "./components/Nav/Nav";
import Home from "./components/Home/Home";
import Contributors from "./components/Contributors/Contributors";

const App = () => {
return (
<Router>
<Routes>
<Route path="/" exact element={<Home />} />
<Route path="/contributors" element={<><Nav /><Contributors /></>} />
</Routes>
</Router>
);
}

export default App;

Improvement:

And if you want to take it further, instead of doing like above, you could set up a Layout component, like this:

import { Outlet } from "react-router-dom";
import Nav from "../Nav/Nav";

const Layout () => {
return (
<>
<Nav />
<Outlet />
</>
);
};

export default Layout;

And render the routes where you want the Nav trough the Layout:

import { BrowserRouter as Router, Routes, Route, matchPath } from "react-router-dom";
import Home from "./components/Home/Home";
import Contributors from "./components/Contributors/Contributors";
import Layout from "./components/Layout/Layout";

const App = () => {
return (
<Router>
<Routes>
<Route path="/" exact element={<Home />} />
<Route element={<Layout />}>
<Route path="/contributors" element={<Contributors />} />
</Route>

</Routes>
</Router>
);
}

export default App;

How to add Navbar and a Sidebar inside the React Router v6 Routes?

Have you tried something like:

return (
<div className="App">
<BrowserRouter>
{logged ? (
<>
<Navbar />
<div className="screens-container">
<Sidebar />
<div className='screens-section-container'>
<Routes>
<Route path='/' element={<Home />} />
<Route path='/customers' element={<Customers />} />
<Route path='/products' element={<Products/>}/>
<Route path='/transactions' element={<Transactions />} />
<Route path='/users' element={<Users />} />
</Routes>
</div>
</div>
</>
): (
<Routes>
<Route path='/' element={<Login />} />
</Routes>
)}
</BrowserRouter>
</div>
);


Related Topics



Leave a reply



Submit