2

I am having issues with what the new syntax should be when it comes to migrating from React Router V5 to React Router V6.

I am new to V6 but in V5 I was using the following code within the component name: MyComponent.js

RR V5

 const theRoute = useRouteMatch();
  const myRoutes = [
    ['Tab One', theRoute.url],
    ['Tab Two', `${theRoute.url}/details`]
 ];

Use Case currently for V5:

  <AppBar
      position="static"
      color="primary"
    >
      <Tabs
        value={location.pathname}
        textColor="inherit"
      >
        <Tab
          label={myRoutes[0][0]}
          value={myRoutes[0][1]}
          component={Link}
          to={myRoutes[0][1]}
        />
        <Tab
          label={myRoutes[1][0]}
          value={myRoutes[1][1]}
          component={Link}
          to={myRoutes[1][1]}
        />
      </Tabs>
    </AppBar>

    <div>
      <Switch>
        <Route path={routes[0][1]}>
          <Main />
        </Route>
        <Route path={routes[1][1]}>
          <ShowDetails />
        </Route>
      </Switch>
    </div>

Within App.js (parent level), I have a route that calls the above MyComponent.js component, which has nested routes.

<div>
  <Switch>
    <Route path="/info/:id">
      <MyComponent />
    </Route>
  </Switch>
</div>

I realise that useRouteMatch() is no longer available in RR V6 but unsure how to achieve the same result I used in V5 above, now in V6?

I looked at useLocation() but it didn't seem to work.

4
  • This is because react-router-dom@6 is capable of rendering relative links and routes. How is this myRoutes array used? Can you share the use case?
    – Drew Reese
    Commented May 20, 2022 at 3:55
  • @DrewReese - use case added to original question.
    – ArthurJ
    Commented May 20, 2022 at 4:12
  • Is all that code nested in some other route? Is that why you previously grabbed the current route's matched URL value so you could build from it? Can you include a bit more code to fill in the picture why the nested route's path prefixes are important?
    – Drew Reese
    Commented May 20, 2022 at 4:31
  • @DrewReese - I have added code relating to App.js route that calls the above MyComponent.js component. This component also has additional nested routes that I build from, from the parent level route. Hope this makes the code clearer.
    – ArthurJ
    Commented May 20, 2022 at 4:45

1 Answer 1

3

App

  • Switch the Switch component for the Routes component that replaced it in v6
  • Move MyComponent into the Route component's element prop, passed as a ReactNode, a.k.a. JSX.
  • Include a trailing route path wildcard character "*" at the end of the path so nested routes can also be matched by this route.

Example:

<div>
  <Routes>
    <Route path="/info/:id/*" element={<MyComponent />} />
  </Routes>
</div>

MyComponent

  • Wrap the nested routes in a Routes component so route matching works. Nested Routes components will build paths relative from the parent route rendering them.
  • Move the routed children components into the Route component's element prop.
  • I suggest making the code more DRY by moving the component you want to render for each route into the myRoutes config and convert to objects from arrays, and map the myRoutes config to the JSX.

Example:

const myRoutes = [
  {
    name: 'Tab One',
    path: "main",
    element: <Main />,
  },
  {
    name: 'Tab Two',
    path: "details",
    element: <ShowDetails />,
  },
];

...

const { pathname } = useLocation();

// Compute the "last path segment" to use for the `Tabs` component
// `value` prop. The last path segment will match against the paths
// that are used for the `Tab` component's `value` prop.

const lastSegment = pathname.split("/").slice(-1).join();

...

<AppBar position="static" color="primary" >
  <Tabs
    value={lastSegment}
    textColor="inherit"
  >
    {myRoutes.map(({ name, path }) => (
      <Tab
        key={path}
        label={name}
        value={path}
        component={Link}
        to={path}
      />
    ))}
  </Tabs>
</AppBar>

<div>
  <Routes>
    {myRoutes.map(({ element, path }) => (
      <Route key={path} path={path} element={element} />
    ))}
  </Routes>
</div>
1
  • const { pathname } = useLocation(); const lastSegment = pathname.split("/").slice(-1).join(); This little bit is exactly what I needed to replace useRouteMatch from react-router v5. I needed to set is-active outside of a NavLink, which seems to be pretty difficult (eg: no built in hook) with react router v6. Thank you! Commented Sep 7, 2022 at 13:52

Not the answer you're looking for? Browse other questions tagged or ask your own question.