4

Using React-Router is there a way manage nested routes that overlay on top of the original route navigation?

I went through the react-router documentation but had trouble finding an example where the original navigation links were removed or hidden on the page.

I'm looking for an example like the below image:

enter image description here

I'm trying to have each tab in the above image be represented by a unique route, and then when a user clicks on an element under a tab, the element's detailed view would show overtop the entire page beneath the app's header. To me, a nested route seems to make sense in this scenario, however, the nested route puts the detailed component beneath the tabbed component. Which is not the user experience I'm looking for.

The routes that I believe make sense given the above would be something like:

Tabs:
/overview/tab1
/overview/tab2
/overview/tab3

Detailed View of Elements:
/overview/tab1/elements/:elementNumber

I was able to achieve this using the following:

export function Navigation() {
  return (
    <div>
      <Switch>
        <Route path="/tabs">
          <TabbedNavigation />
        </Route>
        <Route path="/details">
          <DetailedNavigation />
        </Route>
      </Switch>
    </div>
  );
}
export function TabbedNavigation() {
  return (
    <>
      <Switch>
        <Route path="/tabs/tab1">
          <Tab1 />
        </Route>
        <Route path="/tabs/tab2">
          <Tab2 />
        </Route>
        <Route path="/tabs/tab3">
          <Tab3 />
        </Route>
      </Switch>
    </>
  );
}
export function DetailedNavigation() {
  return (
    <>
      <Switch>
        <Route path="/details/elements/:elementNumber">
          <ElementDetails />
        </Route>
      </Switch>
    </>
  );
}

The above works fine, and provides the user experience I'm looking to achieve, but I feel like there has to be a better way to achieve the same using the react-router api.

Is it possible to have overplayed routes using react-router?

3
  • Why don't you just use absolute or fixed for the CSS position of the DetailedNavigation component and have a margin-top equal to your application header? Commented Jun 25, 2021 at 14:50
  • @foxtrotuniform6969, I'm sorry but not following the suggestion. I understand setting the position attribute, but setting the margin-top to equal the application header I'm a bit lost on. Are you saying to set the margin-top to equal the height of the header? What happens if the height of the header is dynamic and could change based on content? Commented Jun 25, 2021 at 23:21
  • Hey @FlatPenguin, did my answer work for you? I could try another approach if it didn't Commented Jun 29, 2021 at 5:14

3 Answers 3

1

You can achieve that with CSS, set the green container with a position: "relative" style, and the detail view with position: "absolute" and left, right, top, bottom to 0. With this, the details view will cover all other contents of the green container since it gets positioned relative to its closest positioned ancestor (the first ancestor with a position attr)

<GreenContainer style={{ position: "relative" }}>
...
   <DetailsView 
      style={{
        position: "absolute",
        top: 0,
        bottom: 0,
        right: 0,
        left: 0,
      }}
   >
   ...

Here is a codesandbox I set up with the example of nested routes provided in the react-router documentation

https://codesandbox.io/s/react-router-typescript-demo-forked-n0woz?file=/src/example.tsx

note: I'm assuming the green container is a sibling of the header

Sign up to request clarification or add additional context in comments.

Comments

1

You need to wrap the elements that needs to be overwritten within switch

const TabMenu = () => (

  <div >
  <Link to="/tabs/tab1">Tab1</Link> <span>  </span>
  <Link to="/tabs/tab2">Tab2</Link> <span>  </span>
  <Link  to="/tabs/tab3">Tab3</Link>
  </div>)

export function Navigation() {
  return (
    <div>
    <Switch>
      <Route path="/tabs">
        <TabMenu/>
        <TabbedNavigation />
      </Route>
      <Route path="/details/elements/:elementNumber">
        <DetailedNavigation />
      </Route>
    </Switch>
  </div>
  );
}

Because the TabMenu are inside Switch element, it will get replaced with Detailed View.

Here is working code example

https://codesandbox.io/s/react-router-full-page-for-nested-route-s15rx?file=/src/App.js

Comments

0

Using the Outlet component from react-router-dom might be the way to go. You can easily render the <Outlet /> component in the parent in the place you want.

In the case of the element detail, you could do something like:

function Parent() {
  const location = useLocation()
  if (location.pathname === childPath) return <Outlet />

  return ( 
     <ParentRenderStuff />
  )
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.