This error occurs when you call useNavigate or other React Router hooks outside of a Router context provider. React Router hooks require access to the router state provided by a parent Router component.
This error indicates that you're trying to use the `useNavigate` hook (or other React Router hooks like `useLocation`, `useParams`, or `useSearchParams`) in a component that is not wrapped by a Router component. React Router v6 fully embraced hooks for sharing router state, and these hooks depend on React Context provided by a Router component to function properly. The Router component (typically `BrowserRouter`, `HashRouter`, or `MemoryRouter`) acts as a context provider that makes routing information available to all descendant components. When you call `useNavigate()` outside this context tree, React Router cannot access the necessary routing state and throws this error to prevent runtime failures. This is a strict requirement in React Router v6+ and applies to all routing hooks, not just `useNavigate`. The error is actually a helpful guard that catches configuration mistakes early in development.
The most reliable fix is to wrap your entire application with the Router at the root level. In your index.js or main.jsx file, ensure the Router wraps your App component:
// index.js or main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);This ensures all components in your application have access to the Router context. Now any component can safely use useNavigate() and other routing hooks.
Check your component tree to ensure the component using routing hooks is a descendant of the Router. The component must be rendered inside the Router's component tree:
// ✅ Correct: Component is inside Router
<BrowserRouter>
<App>
<MyComponent /> {/* Can use useNavigate here */}
</App>
</BrowserRouter>
// ❌ Wrong: Component is outside Router
<div>
<BrowserRouter>
<App />
</BrowserRouter>
<MyComponent /> {/* Cannot use useNavigate here */}
</div>If you have authentication providers or other context providers, make sure they're nested inside the Router, not wrapping it:
// ✅ Correct order
<BrowserRouter>
<AuthProvider>
<App />
</AuthProvider>
</BrowserRouter>
// ❌ Wrong order
<AuthProvider>
<BrowserRouter>
<App />
</BrowserRouter>
</AuthProvider>If the error occurs in tests, wrap your component with a Router in your test setup:
// Using React Testing Library
import { render } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import MyComponent from './MyComponent';
test('component renders correctly', () => {
render(
<BrowserRouter>
<MyComponent />
</BrowserRouter>
);
// Your test assertions...
});Or create a custom render helper:
// test-utils.js
import { render } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
export function renderWithRouter(ui, options = {}) {
return render(
<BrowserRouter>
{ui}
</BrowserRouter>,
options
);
}
// In your test file
import { renderWithRouter } from './test-utils';
test('component works', () => {
renderWithRouter(<MyComponent />);
});If you're using portals or creating separate React roots, ensure they also have Router context:
// If rendering to a portal
import { createPortal } from 'react-dom';
import { useNavigate } from 'react-router-dom';
function ModalWithNavigation() {
const navigate = useNavigate(); // This works because component is inside Router
return createPortal(
<div className="modal">
<button onClick={() => navigate('/home')}>Go Home</button>
</div>,
document.getElementById('modal-root')
);
}
// The parent component tree should be:
// <BrowserRouter>
// <App>
// <ModalWithNavigation /> {/* Component using portal is inside Router */}
// </App>
// </BrowserRouter>Note: The component creating the portal must be inside the Router, even though the portal content renders elsewhere in the DOM.
React Router provides a useInRouterContext hook to check if a component has Router context. Use it to debug:
import { useInRouterContext } from 'react-router-dom';
function MyComponent() {
const hasRouter = useInRouterContext();
console.log('Has router context:', hasRouter);
if (!hasRouter) {
console.error('Component is not inside a Router!');
return <div>Router context missing</div>;
}
// Safe to use routing hooks now
const navigate = useNavigate();
// ...
}This helps identify exactly where in your component tree the Router context is missing.
Router Types and When to Use Each:
React Router provides several Router components for different environments:
- BrowserRouter: For web applications using HTML5 history API (most common)
- HashRouter: For web apps that need hash-based routing (legacy or static hosting)
- MemoryRouter: For testing or non-browser environments (React Native)
- StaticRouter: For server-side rendering
Hooks vs Components:
React Router v6 encourages hooks over components. All these hooks require Router context:
- useNavigate: Programmatic navigation
- useLocation: Current location object
- useParams: URL parameters
- useSearchParams: Query string parameters
- useMatch: Match against a pattern
- useRoutes: Render routes from JS objects
Context Provider Ordering:
When using multiple context providers (auth, theme, state management), the general rule is:
1. Router should be outermost (or very close to root)
2. Authentication providers inside Router
3. Theme/UI providers inside auth
4. State management providers last
This order allows auth callbacks to use navigation, and state management to access routing.
Server-Side Rendering:
If you're doing SSR with frameworks like Next.js or Remix, they provide their own routing solutions. Don't mix React Router with Next.js's built-in routing - they're incompatible.
V6 vs V5 Differences:
In React Router v5, you could use withRouter HOC or access history directly. V6 removed these patterns in favor of hooks, making Router context even more critical. If migrating from v5, ensure all components previously using withRouter are now inside a Router component.
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