React Router v6 - nested routing without Outlet

Viewed 5449

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.

4 Answers

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>

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.

It is possible to use nested 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. Nest the Routes

Nest the <UserPage /> component in the <Users /> component 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

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.

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>
Related