Fix: No Routes Matched Location in React Router v6
Quick Answer
How to fix 'No routes matched location' in React Router v6 — caused by missing Routes wrapper, wrong path syntax, nested route mismatches, and v5 to v6 migration issues.
The Error
You set up React Router v6 and the page renders blank, or you see this warning in the console:
No routes matched location "/dashboard"Or the component just does not render at all — no error, just a blank area where the route component should appear.
Other related symptoms:
- The URL changes when you click a
<Link>, but the component does not render. - Nested routes show the parent but not the child component.
- All routes render a blank page after upgrading from React Router v5 to v6.
- The route matches on the root
/but not on any other path. - A 404 component always renders even when the path exists.
Why This Happens
React Router v6 introduced significant breaking changes from v5. The most common causes of routes not matching:
- Missing
<Routes>wrapper around<Route>elements (v6 requires this). - Using
<Switch>from v5 — it no longer exists in v6. - Using
component=orrender=props instead ofelement=. - Wrong path syntax — v6 paths are relative by default in nested routes.
- Missing
<Outlet>in parent route components for nested routes to render into. exactprop on<Route>— v6 does not useexact(all routes match exactly by default).- Rendering
<Route>outside of<Routes>— a<Route>outside<Routes>does nothing in v6.
Fix 1: Replace Switch with Routes and Update Route Syntax
React Router v6 replaces <Switch> with <Routes> and changes how you pass components:
Broken — v5 syntax in a v6 project:
import { Switch, Route } from "react-router-dom";
function App() {
return (
<Switch>
<Route path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/dashboard" render={() => <Dashboard />} />
</Switch>
);
}Fixed — v6 syntax:
import { Routes, Route } from "react-router-dom";
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
);
}Key differences:
<Switch>→<Routes>component={Home}→element={<Home />}render={() => <Dashboard />}→element={<Dashboard />}- Remove
exact— all routes in v6 match exactly by default.
Fix 2: Wrap All Routes in a Single Routes Component
Every <Route> must be a direct child of <Routes>. You cannot render a <Route> standalone:
Broken — Route outside of Routes:
function App() {
return (
<div>
<Navbar />
<Route path="/home" element={<Home />} /> {/* Does nothing */}
<Route path="/about" element={<About />} /> {/* Does nothing */}
</div>
);
}Fixed:
function App() {
return (
<div>
<Navbar />
<Routes>
<Route path="/home" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</div>
);
}Fix 3: Add Outlet to Parent Components for Nested Routes
Nested routes in v6 require the parent component to render an <Outlet> — a placeholder where the child route renders:
Broken — parent has no Outlet:
// Route config
<Routes>
<Route path="/dashboard" element={<Dashboard />}>
<Route path="settings" element={<Settings />} />
<Route path="profile" element={<Profile />} />
</Route>
</Routes>
// Dashboard component — missing Outlet
function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
{/* Settings and Profile never render because there's no Outlet */}
</div>
);
}Fixed — add Outlet:
import { Outlet } from "react-router-dom";
function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<nav>
<Link to="settings">Settings</Link>
<Link to="profile">Profile</Link>
</nav>
<Outlet /> {/* Child routes render here */}
</div>
);
}Pro Tip: Think of
<Outlet>as a slot. When the URL matches a child route like/dashboard/settings, React Router renders the parent (Dashboard) with<Outlet>replaced by the child component (Settings). Without<Outlet>, the child has nowhere to render.
Fix 4: Fix Nested Route Paths (Relative vs Absolute)
In React Router v6, nested route paths are relative to their parent by default:
Broken — absolute paths in nested routes:
<Routes>
<Route path="/dashboard" element={<Dashboard />}>
<Route path="/dashboard/settings" element={<Settings />} /> {/* Wrong */}
<Route path="/dashboard/profile" element={<Profile />} /> {/* Wrong */}
</Route>
</Routes>Fixed — relative paths:
<Routes>
<Route path="/dashboard" element={<Dashboard />}>
<Route path="settings" element={<Settings />} /> {/* Matches /dashboard/settings */}
<Route path="profile" element={<Profile />} /> {/* Matches /dashboard/profile */}
</Route>
</Routes>Render the index route for the parent path itself:
<Routes>
<Route path="/dashboard" element={<Dashboard />}>
<Route index element={<DashboardHome />} /> {/* Renders at /dashboard */}
<Route path="settings" element={<Settings />} />
</Route>
</Routes>The index prop marks the default child route — it renders when the parent path matches exactly.
Fix 5: Fix Link Paths in Nested Routes
<Link> paths in nested components are also relative in v6 unless they start with /:
Broken — missing leading slash in a nested link:
// Inside Dashboard (rendered at /dashboard)
function Dashboard() {
return (
<Link to="home">Go Home</Link> // Navigates to /dashboard/home, not /home
);
}Fixed — use absolute paths with leading slash:
function Dashboard() {
return (
<Link to="/home">Go Home</Link> // Navigates to /home
);
}Or use relative paths intentionally:
<Link to="../">Up one level</Link>
<Link to="settings">Settings (relative to current route)</Link>Fix 6: Add a Catch-All 404 Route
If no routes match, React Router renders nothing (an empty <Routes>). Add a wildcard route to render a 404 page:
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/dashboard/*" element={<Dashboard />} />
<Route path="*" element={<NotFound />} /> {/* Catches all unmatched paths */}
</Routes>The * wildcard matches any unmatched path. Place it last — <Routes> picks the best match, not the first match, but putting * last makes intent clear.
For nested route groups, add /* to the parent:
<Route path="/dashboard/*" element={<Dashboard />}>
{/* Nested routes work because /* allows matching sub-paths */}
<Route path="settings" element={<Settings />} />
</Route>Without /* on the parent, the parent only matches /dashboard exactly and nested paths like /dashboard/settings will not render the parent.
Common Mistake: Forgetting
/*on parent routes that have nested children. If your parent route ispath="/dashboard"(without/*), it matches/dashboardexactly but not/dashboard/settings. Add/*whenever a route has children.
Fix 7: Fix useNavigate and Programmatic Navigation
React Router v6 replaced useHistory with useNavigate:
Broken — v5 hook in v6:
import { useHistory } from "react-router-dom"; // Does not exist in v6
function LoginPage() {
const history = useHistory();
const handleLogin = () => {
history.push("/dashboard");
};
}Fixed:
import { useNavigate } from "react-router-dom";
function LoginPage() {
const navigate = useNavigate();
const handleLogin = () => {
navigate("/dashboard");
// navigate(-1); // Go back
// navigate("/", { replace: true }); // Replace current history entry
};
}Fix 8: Ensure BrowserRouter Wraps the App
The entire Router context must wrap your app. If <BrowserRouter> (or <HashRouter>) is missing or placed incorrectly, no routing works at all:
Broken — Routes outside of Router:
// main.jsx
ReactDOM.createRoot(document.getElementById("root")).render(
<App /> // App contains Routes but no Router wrapping it
);
// App.jsx
function App() {
return (
<BrowserRouter> {/* Router is inside — this is fine */}
<Routes>...</Routes>
</BrowserRouter>
);
}The above actually works if BrowserRouter is inside App. The error occurs when <Routes> is used with no <Router> ancestor at all:
// Broken — no Router anywhere
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
</Routes>
);
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);Fixed — wrap at the entry point:
ReactDOM.createRoot(document.getElementById("root")).render(
<BrowserRouter>
<App />
</BrowserRouter>
);For server-side rendering (Next.js), you do not use React Router — Next.js has its own file-based router. For SSR hydration issues, see Fix: Next.js Hydration Failed.
Still Not Working?
Check the installed version. Run npm list react-router-dom to confirm you have v6. If you have v5 installed, either upgrade to v6 or use v5 syntax throughout.
Check for multiple router instances. Having both react-router and react-router-dom installed at different major versions can cause conflicts. Run npm ls react-router to check.
Check for <Route> inside fragments. <Routes> only recognizes direct children. Wrapping <Route> elements in a <React.Fragment> or array may cause them not to be recognized:
// Broken
<Routes>
<>
<Route path="/" element={<Home />} />
</>
</Routes>
// Fixed
<Routes>
<Route path="/" element={<Home />} />
</Routes>Check hash vs history routing. If your app is deployed on a static host without server-side routing support, use <HashRouter> instead of <BrowserRouter>. With <BrowserRouter>, navigating directly to /about requires the server to serve index.html for that path. For Cloudflare Pages and similar platforms, add a redirect rule to serve index.html for all routes.
For other React rendering issues like components re-rendering too often, see Fix: React Too Many Re-renders or Fix: React useEffect Infinite Loop.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: React Context Not Updating / Re-rendering Components
How to fix React Context not triggering re-renders — caused by mutating state directly, wrong provider placement, stale closures, and missing value changes that React can detect.
Fix: CSS Custom Properties (Variables) Not Working or Not Updating
How to fix CSS custom properties not applying — wrong scope, missing fallback values, JavaScript not setting variables on the right element, and how CSS variables interact with media queries and Shadow DOM.
Fix: Next.js Middleware Not Running (middleware.ts Not Intercepting Requests)
How to fix Next.js middleware not executing — wrong file location, matcher config errors, middleware not intercepting API routes, and how to debug middleware execution in Next.js 13 and 14.
Fix: React Query (TanStack Query) Infinite Refetching Loop
How to fix React Query refetching infinitely — why useQuery keeps fetching, how object and array dependencies cause loops, how to stabilize queryKey, and configure refetch behavior correctly.