Ar26
Ar26

Reputation: 1119

React Router v6 - nested routing without Outlet

I'm using react-router v6, Is it possible to use nested routes without using the Outlet component?

For example: I have a users page and onClick on a user component it should navigate to the specific user page,

Current try:

 <Routes>
   <Route path="/" element={<Home />} />
   <Route path="/users" element={<Users />} />
     <Route path=":id" element={<UserPage/>} />
 </Routes>

And on click on a specific user:

const gotoUserPage = () => {
  navigate('1')
}

The gotoUserPage change the URL from '/users' to '/users/1' but the userPage component doesn't render.

Upvotes: 12

Views: 15298

Answers (6)

rrain
rrain

Reputation: 51

I am using nested <Routes></Routes> component in react-router-dom v6 and it is working. But in console sometimes there is warning message "No routes matched location ...someLocation..." and i guess if this method is correct. But it is not convenient for me to use <Outlet/>. In the example below PageRouting contains Page. Page contains NestedPageRouting. And NestedPageRouting contains NestedPage. Slash and asterisk (/*) in the end of path segment allow nested routing. First slash in the path in comments assumes that <PageRouting/> is the root routing.

function PageRouting(){
  return <Routes>
    {/* path: /page */}
    <Route path="page/*" element={<Page/>}/>
    <Route path='*' element={<div>No routes matched</div>}/>
  </Routes>
}

function Page(){
  return <div>
    <div>Some content</div>
    <NestedPageRouting/>
  </div>
}

function NestedPageRouting(){
  return <Routes>
    {/* path: /page/nestedPage */}
    <Route path="nestedPage/*" element={<NestedPage/>}/>
    <Route path='*' element={<div>No routes matched</div>}/>
  </Routes>
}

function NestedPage(){
  return <div>Some Nested Content</div>
}

Upvotes: 1

tundeph
tundeph

Reputation: 31

It is possible to use routes without using the <Outlet /> component, what you simply need to do is shown below. Use the same path of the parent component and add the :id:

 <Routes>
   <Route path="/" element={<Home />} />
   <Route path="/users" element={<Users />} />
   <Route path="users/:id" element={<UserPage/>} />
 </Routes>

However if you are concerned about the fact that the <Outlet /> component renders on the same page with the Parent component when nested, then you can hide the Parent component when the child component is active like this:

1. Use Flat Routes

Add the <UserPage /> component in the routes like this:

<Routes>
   <Route path="/" element={<Home />} />
   <Route path="users" element={<Users />} >
     <Route path=":id" element={<UserPage />} />
   </Route>
 </Routes>

2. Parent Component Conditional Render

Add a condition to NOT render contents of Parent component if there exist a params.id property, this uses Outlet but helps you avoid showing some elements.

let params = useParams();
<div>
!params.id && (<div>
*render your contents here* </div>)
<Outlet />
</div>

So whenever the child component is loaded, the Parent component is not visible.

Upvotes: 3

Abdullah Mehboob
Abdullah Mehboob

Reputation: 81

Yes you can do that with some trick. Here is my trick

  • first crate a outlet component ( <OutletPage /> )
  • then create page which actually needs to render when somebody visit that route

Like this

<Route path="profile" element={<ProfilePageOutlet />}>
     <Route index element={<ProfilePage />} />
     <Route path="my-profile" element={<MyProfilePage />} />
</Route>

<ProfilePageOutlet /> looks like this

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

function ProfilePageOutlet() {
  return <Outlet />;
}

export default ProfilePageOutlet;

<MyProfilePage /> is a simple page

Upvotes: 0

Drew Reese
Drew Reese

Reputation: 203408

Is it possible to use nested routes without using the Outlet component?

No, an Outlet component is required in order to render the nested Route components.

Either the Users component must render an Outlet component, or you can render directly an Outlet as a layout component.

<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/users" element={<Outlet />}>
    <Route index element={<Users />} />        // "/users"
    <Route path=":id" element={<UserPage/>} /> // "/users/:id"
  </Route>
</Routes>

Though, a better or more accurate question may be, do you even need to explicitly render an Outlet as a layout element? The answer may surpisingly be "no". Route components render an Outlet by default on the element prop.

The default <Route element> is an <Outlet>. This means the route will still render its children even without an explicit element prop, so you can nest route paths without nesting UI around the child route elements.

You can simply wrap some nested routes in a Route and specify only the path for nesting, and the nested routes will be rendered into an Outlet by default.

<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/users">
    <Route index element={<Users />} />        // "/users"
    <Route path=":id" element={<UserPage/>} /> // "/users/:id"
  </Route>
</Routes>

Upvotes: 22

Roman Panaget
Roman Panaget

Reputation: 2428

This is an optimised way of doing what @hellocng has explained:

<Routes>
   <Route path="/" element={<Home />} />
   <Route path="users" element={<Outlet />}>
     <Route index element={<Users />} />
     <Route path=":id" element={<UserPage />} />
   </Route>
 </Routes>

Upvotes: 4

hellocng
hellocng

Reputation: 124

What's wrong with using the <Outlet/> component? It tells React Router where to render the <UserPage/> so without it, there is no place for the page to render, as expected.

If you are wondering how to render the page without it being a child of the <Users/> page, then you can try the following:

<Routes>
   <Route path="/" element={<Home />} />
   <Route path="users" element={<Outlet />} />
     <Route path="/" element={<Users />} />
     <Route path=":id" element={<UserPage />} />
 </Routes>

There are definitely times when a whole different component is necessary, but in most cases, components share certain components, such as nav bar and containers. If you have a nav bar in both the Users and UserPage components, then you may want to consider refactoring it out of both, and put it in a parent component with the nav bar and Outlet. This will help with managing conponents as you scale.

Upvotes: 6

Related Questions