This React Router v6 error occurs when a <Route> component is rendered outside of a <Routes> wrapper, or when using the incorrect v6 syntax. Route components must always be direct children of a Routes component.
This error is specific to React Router v6 and occurs when the routing structure violates React Router's component hierarchy rules. In React Router v6, every <Route> component must be a direct child of a <Routes> component - they cannot exist independently or be wrapped in custom components without proper adaptation. The error typically appears when developers try to render Route components directly in JSX without wrapping them in a Routes container, or when migrating from React Router v5 where the syntax was different. React Router v6 requires this strict hierarchy because it statically analyzes the Routes children to build the routing configuration, rather than rendering them dynamically. Understanding this constraint is crucial because it represents a fundamental architectural change in how React Router v6 handles routing compared to previous versions. The Routes component needs direct access to Route components to perform optimizations and rank routes by specificity.
Check that all your <Route> components are wrapped in a <Routes> component. This is the most common fix.
Incorrect (causes error):
import { Route } from 'react-router-dom';
function App() {
return (
<div>
<Route path="/about" element={<About />} />
<Route path="/" element={<Home />} />
</div>
);
}Correct:
import { Routes, Route } from 'react-router-dom';
function App() {
return (
<div>
<Routes>
<Route path="/about" element={<About />} />
<Route path="/" element={<Home />} />
</Routes>
</div>
);
}If you're migrating from v5, replace the children syntax with the element prop. This is a breaking change in v6.
v5 syntax (no longer works):
<Routes>
<Route path="/about">
<About />
</Route>
</Routes>v6 syntax:
<Routes>
<Route path="/about" element={<About />} />
</Routes>Note: The <Route children={<Component />} /> syntax is now reserved exclusively for nested route definitions, not for rendering components.
Custom route wrappers like PrivateRoute need to be refactored for v6. They can no longer wrap <Route> components directly.
Old v5 pattern (broken in v6):
function PrivateRoute({ children, ...rest }) {
return (
<Route {...rest}>
{isAuthenticated ? children : <Navigate to="/login" />}
</Route>
);
}
// Usage
<Routes>
<PrivateRoute path="/dashboard">
<Dashboard />
</PrivateRoute>
</Routes>v6 pattern - use element wrapper:
function PrivateRoute({ children }) {
const isAuthenticated = useAuth();
return isAuthenticated ? children : <Navigate to="/login" replace />;
}
// Usage
<Routes>
<Route
path="/dashboard"
element={
<PrivateRoute>
<Dashboard />
</PrivateRoute>
}
/>
</Routes>React Router v6 only accepts <Route> or <React.Fragment> as direct children of <Routes>. Remove any other components.
Incorrect:
<Routes>
<div className="route-wrapper">
<Route path="/about" element={<About />} />
</div>
</Routes>Correct:
<Routes>
<Route path="/about" element={<About />} />
</Routes>If you need wrapper styling, apply it to the routed components themselves or use a layout route:
<Routes>
<Route element={<Layout />}>
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Route>
</Routes>If you're conditionally rendering routes based on authentication or other state, ensure the Routes wrapper is always present.
Incorrect:
function App() {
const isAuthenticated = useAuth();
return (
<div>
{isAuthenticated && <Route path="/dashboard" element={<Dashboard />} />}
</div>
);
}Correct:
function App() {
const isAuthenticated = useAuth();
return (
<div>
<Routes>
{isAuthenticated && <Route path="/dashboard" element={<Dashboard />} />}
<Route path="/login" element={<Login />} />
</Routes>
</div>
);
}Why React Router v6 enforces this constraint:
React Router v6 uses static analysis of the Routes children to build an optimized routing tree. It ranks routes by specificity, handles nested routes more efficiently, and enables features like relative routing. This static analysis requires direct access to Route components at compile time, which is why they must be immediate children of Routes.
Layout routes pattern:
One of v6's most powerful features is layout routes - routes that render an Outlet for child routes:
function Layout() {
return (
<div>
<nav>Navigation</nav>
<Outlet /> {/* Child routes render here */}
</div>
);
}
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
</Route>
</Routes>Using React.Fragment for grouping:
If you need to group routes logically in your code without affecting rendering, use React.Fragment:
<Routes>
<React.Fragment>
{/* Admin routes */}
<Route path="/admin" element={<AdminLayout />}>
<Route path="users" element={<Users />} />
<Route path="settings" element={<Settings />} />
</Route>
</React.Fragment>
<React.Fragment>
{/* Public routes */}
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</React.Fragment>
</Routes>Alternative pattern for route protection:
Instead of wrapper components, consider using a layout route with Outlet:
function RequireAuth() {
const isAuthenticated = useAuth();
return isAuthenticated ? <Outlet /> : <Navigate to="/login" />;
}
<Routes>
<Route element={<RequireAuth />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/profile" element={<Profile />} />
</Route>
</Routes>This pattern is cleaner and more idiomatic in v6 than wrapping individual routes.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite