Search code examples
react-routerreact-router-dom

Changing from useRouteMatch to useMatch / useLocation


Looking at the documentation for react-router 6, the useRouteMatch hook was removed in favor of useMatch. Since the in v5 useRouteMatch either

takes no argument and returns the match object of the current <Route> or takes a single argument

Does that mean that when useRouteMatch is used without an argument I could just use the pathname from useLocation? And should I still pass that to useMatch?

Example of what I'm trying to convert to version 6 (v5 code):

const match = useRouteMatch();
if (!match) return null;
return (
  <Switch>
    <Route path={`${match.path}/:Id?`} component={ImportedComponent} />
  </Switch>
);

Changing this to v6:

const match = useMatch(); // which argument does this take?
if (!match) return null;
return (
  <Routes>
    <Route path={`${match.path}/:Id?`} element={<ImportedComponent />} />
  </Routes>
);

Solution

  • The useMatch Hook

    useMatch takes a single path pattern argument, and returns a PathMatch object or null if there is a match to the current location, e.g. the current URL path.

    Example:

    Given the current location is "/test/foo/bar".

    • useMatch("/test/foo/bar"); returns:

      {
        params: {},
        pathname: "/test/foo/bar",
        pathnameBase: "/test/foo/bar",
        pattern: {
          path: "/test/foo/bar",
          caseSensitive: false,
          end: true,
        },
      }
      
    • useMatch("/test/:segment1/:segment2"); returns:

      {
        params: {
          segment1: "foo",
          segment2: "bar",
        },
        pathname: "/test/foo/bar",
        pathnameBase: "/test/foo/bar",
        pattern: {
          path: "/test/:segment1/:segment2",
          caseSensitive: false,
          end: true,
        },
      }
      
    • useMatch("/bizzbuzz"); returns:

      null
      

    Rendering Descendent Routes

    In react-router-dom@6 the Routes component will "build" the paths it manages all relative to it's parent's Route component's path. There's no need to build these paths yourself manually. If the parent path is not currently matched then the component is not rendered and the Routes and descendent routes are not rendered.

    Example:

    Parent

    <Routes>
      ...
      <Route path="/child/*" element={<Child />} />
      ...
    </Routes>
    

    Child

    return (
      <Routes>
        <Route path="/:Id?" element={<ImportedComponent />} />
      </Routes>
    );
    

    Here the Child component will be rendered whenever "/child/*" is the match. The route on path="/:Id?" will be matched and render its element content when it's a match. Since Id is an optional parameter this route will match "/child", "/child/123", and any other sub-route of "/child".

    Demo

    Edit changing-from-useroutematch-to-usematch-uselocation