This error occurs when you call the useParams hook in a component that is not wrapped by a React Router component like BrowserRouter or HashRouter. The hook requires access to React Router's context to retrieve URL parameters, which is only available within the router tree.
React Router hooks like useParams rely on React context to access routing information. When you call useParams, React looks up the component tree for a Router provider (such as BrowserRouter, HashRouter, or MemoryRouter) that supplies the routing context. If no router is found in the component's ancestor tree, React Router throws this invariant violation error. This error is React Router's way of telling you that the component calling useParams is either rendered outside the router entirely, or the router component has not been properly set up in your application's component hierarchy. The hook needs to be called within a component that is a descendant of a Router component to function correctly.
Check your root component (usually App.tsx or index.tsx) and ensure that BrowserRouter (or another Router variant) wraps all components that need routing. The Router must be a parent of any component using useParams.
// WRONG - useParams used outside Router
import { useParams } from "react-router-dom";
function App() {
return (
<div>
<UserProfile /> {/* This will fail */}
</div>
);
}
function UserProfile() {
const { id } = useParams(); // ERROR: No Router in tree
return <div>User {id}</div>;
}
// CORRECT - Router wraps components using hooks
import { BrowserRouter } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/user/:id" element={<UserProfile />} />
</Routes>
</BrowserRouter>
);
}
function UserProfile() {
const { id } = useParams(); // Works correctly
return <div>User {id}</div>;
}If your Router is nested inside other components, move it higher up, ideally in your root file (index.tsx or main.tsx). This ensures all components have access to routing context.
// index.tsx or main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);The component calling useParams must be rendered as part of a Route element. Make sure your routes are properly configured and the component is included in the routing structure.
import { Routes, Route } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/user/:id" element={<UserProfile />} />
<Route path="/post/:postId" element={<PostDetail />} />
</Routes>
</BrowserRouter>
);
}
function UserProfile() {
const { id } = useParams();
return <div>User Profile: {id}</div>;
}If you encounter this error in tests, wrap your component with MemoryRouter in your test file. MemoryRouter provides the routing context needed for hooks without requiring browser APIs.
import { render, screen } from "@testing-library/react";
import { MemoryRouter, Route, Routes } from "react-router-dom";
import UserProfile from "./UserProfile";
test("renders user profile", () => {
render(
<MemoryRouter initialEntries={["/user/123"]}>
<Routes>
<Route path="/user/:id" element={<UserProfile />} />
</Routes>
</MemoryRouter>
);
expect(screen.getByText(/User Profile: 123/)).toBeInTheDocument();
});Multiple versions of react-router-dom can cause context mismatches. Check your package.json and lock file to ensure only one version is installed.
# Check for duplicate installations
npm ls react-router-dom
# If duplicates found, remove node_modules and reinstall
rm -rf node_modules package-lock.json
npm install
# Or with yarn
yarn why react-router-dom
rm -rf node_modules yarn.lock
yarn installIf you cannot restructure your component hierarchy, consider passing route parameters as props from a parent component that is within the Router context.
// Parent component (inside Router)
function UserProfileContainer() {
const { id } = useParams();
return <UserProfileDisplay userId={id} />;
}
// Child component (doesn't need Router context)
function UserProfileDisplay({ userId }: { userId: string }) {
return <div>User Profile: {userId}</div>;
}React Router v6 uses different exports than v5. Ensure you're importing from the correct package and using the right Router component for your version.
// React Router v6
import { BrowserRouter, Routes, Route, useParams } from "react-router-dom";
// React Router v5 (older)
import { BrowserRouter, Switch, Route, useParams } from "react-router-dom";
// Check your installed version
npm list react-router-domThis error is part of React Router's invariant system, which validates that hooks are used correctly at runtime. The error is intentionally thrown to prevent undefined behavior that would occur if useParams tried to access context that doesn't exist. In some advanced scenarios, you might encounter this error when using Server-Side Rendering (SSR) with frameworks like Next.js or Remix. These frameworks have their own routing systems, and mixing them with React Router can cause conflicts. If you're using Next.js, consider using Next.js's built-in routing with useRouter from next/router instead of React Router. For micro-frontend architectures where multiple apps share routing state, ensure each app has its own Router instance or use a shared routing context provider. When working with React Router v6.4+ data APIs (createBrowserRouter and RouterProvider), the error may also occur if you try to use hooks outside the routes defined in the router configuration. In such cases, ensure your routes are properly configured in the router object passed to RouterProvider.
Prop spreading could cause security issues
Prop spreading could cause security issues
Error: error:0308010C:digital envelope routines::unsupported
Error: error:0308010C:digital envelope routines::unsupported
React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.
React Hook useEffect placed inside a condition
Hook can only be called inside the body of a function component
Hook can only be called inside the body of a function component
Rollup failed to resolve import during build
How to fix "Rollup failed to resolve import" in React