Michael Johansen
Michael Johansen

Reputation: 5106

React Router v6: Route tracking with matchRoutes

We used our own in-house Route-component to track routes in react-router-dom v5. It looked roughly like this:

import { Switch, Route } from 'react-router-dom';

// EDIT: This was React-Router v5 code, in v6 <Switch> is replaced by <Routes>
//       and <Route component={}> is replaced by <Route element={}>

const routes = () => (
  <Switch>
    <TrackedRoute title="title to track" path="/path/home" component={Home} />
    <TrackedRoute title="title to track" path="/path/contact" component={Contact} />
  </Switch>
)

const TrackedRoute = ({ title, ...others }) => {
  doTrackingThings(title);
  return (
    <Route {...others} />
  );
}

But in React Router v6 the Routes component only accepts its own <Route> objects. This is enforced through type equality. Additionally optional params are no longer allowed in route paths, which made our tracking more complicated. If we want to track which route the user is on, how do we do this in React Router v6?

Upvotes: 2

Views: 6101

Answers (3)

Michael Johansen
Michael Johansen

Reputation: 5106

We ended up moving the tracking to a separate component. It looks roughly like this:

import { BrowserRouter, Routes, Route, matchRoutes, useLocation } from 'react-router-dom';

const app = () => (
  <BrowserRouter>
    <Routes>
      <Route path="/path/home" element={<Home />} />
      <Route path="/path/contact" element={<Contact />} />
    </Routes>
    <RouteTracker />
  </BrowserRouter>
);

const RouteTracker = () => {
  // Add our tracking, find all routes that match and track it
  const currentLocation = useLocation();
  const someRoutes = [
    { path: "/path/home" },
    { path: "/path/contact" },
  ];
  const matches = matchRoutes(someRoutes, currentLocation);
  doTrackingThings(matches);
  return null;
}

We wanted to do tracking in one single location (the app is large). For someone else having a <Tracked> component like the other answers suggest may be a better fit.

Upvotes: 2

krishnaacharyaa
krishnaacharyaa

Reputation: 24980

Switch is changed as Routes in v6. As we have nested elements , we can return the props of children to parent.

const Tracked = ({title, children})=>{
 // use title here
 return children // as props for the parent 
}

Call it as:

<Routes>
  <Route path="/home" element={<Tracked title='title'><Home/></Tracked>}/>
</Routes>

Upvotes: 0

Andrey Smolko
Andrey Smolko

Reputation: 1154

I would make a component e.g. Tracked and wrap in it element itself:

const Tracked = ({title, children})=>{
 doTrackingThings(title);
 return children
}

//then

<Routes>
  <Route path="/home" element={<Tracked title='home'><Home/></Tracked>}/>
</Routes>

Upvotes: 1

Related Questions