Router: No routes matched location "/" error react-router-dom v6

Viewed 1220

I recently migrated from react-router-dom V5 to v6 and I got the following message below:

index.js:44 No routes matched location "/"

Here is how my App component looks

const joinedSignupRoutes = `/(${allSteps
  .map((step) => step.path.substr(1))
  .join('|')})`;

const App = ({ history }) => {
  return (
    <ConnectedRouter history={history}>
      <Routes>
        <Route path={joinedSignupRoutes} element={<RegistrationRoutes />} />

Any thoughts on how to solve this will be very much appreciated.

1 Answers

Add a route for path "/" since it's missing.

Example:

const joinedSignupRoutes = `/(${allSteps
  .map((step) => step.path.substr(1))
  .join('|')})`;

const App = ({ history }) => {
  return (
    <ConnectedRouter history={history}>
      <Routes>
        <Route path="/" element={<h1>Home</h1>} /> // <-- replace with actual component
        <Route path={joinedSignupRoutes} element={<RegistrationRoutes />} />
      </Routes>
    </ConnectedRouter>
  );
};

Update

... instead of having <Route path="/" element={<h1>Home</h1>} /> as the landing page I want to have the <Route path={joinedSignupRoutes} element={<RegistrationRoutes />} />. That is the first page to be viewed when the App runs should be the RegistrationRoutes component.

You still need to render a route on path "/" to maintain an invariant that react-router-dom@6 enforces, but you can render anything on this route. In this case you can render a redirect to your joinedSignupRoutes route.

Example:

import { ...., Navigate } from 'react-router-dom';

const joinedSignupRoutes = `/(${allSteps
  .map((step) => step.path.substr(1))
  .join('|')})`;

const App = ({ history }) => {
  return (
    <ConnectedRouter history={history}>
      <Routes>
        <Route
          path="/"
          element={<Navigate to={joinedSignupRoutes} replace />} 
        />
        <Route path={joinedSignupRoutes} element={<RegistrationRoutes />} />
      </Routes>
    </ConnectedRouter>
  );
};

Update 2

// Joins all signup paths to a singel route to multimatch it against.
// eg. path="/(step-1|step-2|step-3)"
const joinedSignupRoutes = `/(${allSteps
  .map((step) => step.path.substr(1))
  .join("|")})`;

react-router-dom@5 routes could take path props that used regular expressions. This is not the case in react-router-dom@6.

See What Happened to Regexp Routes paths?

Regexp route paths were removed for two reasons:

  1. Regular expression paths in routes raised a lot of questions for v6's ranked route matching. How do you rank a regex?

  2. We were able to shed an entire dependency (path-to-regexp) and cut the package weight sent to your user's browser significantly. If it were added back, it would represent 1/3 of React Router's page weight!

After looking at a lot of use cases, we found we can still meet them without direct regexp path support, so we made the tradeoff to significantly decrease the bundle size and avoid the open questions around ranking regexp routes.

The majority of regexp routes were only concerned about one URL segment at a time and doing one of two things:

  1. Matching multiple static values
  2. Validating the param in some way (is a number, not a number, etc.)

To handle this in v6 you will need an explicit route for each path. Redirect from "/" to "/step-1"

Example:

import { ...., Navigate } from 'react-router-dom';

const joinedSignupRoutes = `/(${allSteps
  .map((step) => step.path.substr(1))
  .join('|')})`;

const App = ({ history }) => {
  return (
    <ConnectedRouter history={history}>
      <Routes>
        <Route
          path="/"
          element={<Navigate to={allSteps[0]} replace />} 
        />
        {allSteps.map(path => (
          <Route
            key={path}
            path={path}
            element={<RegistrationRoutes />}
          />
        ))}
      </Routes>
    </ConnectedRouter>
  );
};
Related