Search code examples
reactjsreact-routerreact-router-dom

Error: useHref() may be used only in the context of a <Router> component. It works when I directly put the url as localhost:3000/experiences


I have a navbar that is rendered in every route while the route changes on click.

./components/navbar.jsx

import React, { Component } from 'react';
import '../App.css';
import { Link } from 'react-router-dom';



class Navbar extends Component {
    constructor(props) {
        super(props);
        this.state = {};
    }
    render() {
        return (
            <div id = 'navbar'>

                <div className='name-head'>
                    My Name
                </div>
            
            
                <div id = 'nav-links-container'>
                    
                    <Link to='/experiences'>
                        <div className = 'nav-links'>
                            Experiences
                        </div>
                    </Link>

                    <div className = 'nav-links'>
                        Projects
                    </div>

                    <div className = 'nav-links'>
                        Skills
                    </div>

                    <div className = 'nav-links'>
                        Resume
                    </div>

                </div>
                
            </div>
        );
    }
}

export default Navbar;

./components/experiences.jsx

import React, { Component } from 'react';


class Experiences extends Component {
    
    render() { 
        return (
            <div>
                <h1>hi</h1>
            </div>
        );
    }
}
 
export default Experiences;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import reportWebVitals from './reportWebVitals';
import Navbar from './components/Navbar';
import Home from './components/Home';
import Experiences from './components/experience';

import {
  BrowserRouter as Router, 
  Routes, 
  Route
} from 'react-router-dom';



ReactDOM.render(

  <React.StrictMode>

    <Navbar />

    <Router>

      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/experiences" element={<Experiences />} />
      </Routes>

    </Router>

  </React.StrictMode>,

  document.getElementById('root')
);


reportWebVitals();

The error doesn't come when I remove the <Link> from the experiences tag in navbar. There is a similar question posted here: Error: useHref() may be used only in the context of a <Router> component but doesn't help.

I'm using react router v6


Solution

  • Issue

    You are rendering the navbar outside the routing context. The Router isn't aware of what routes the links are attempting to link to that it is managing. The reason routing works when directly navigating to "/experiences" is because the Router is aware of the URL when the app mounts.

    <Navbar /> // <-- outside router!!
    
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/experiences" element={<Experiences />} />
      </Routes>
    </Router>
    

    Solution

    Move it inside the routing context so the Router is aware and can manage routing correctly.

    <Router>
      <Navbar />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/experiences" element={<Experiences />} />
      </Routes>
    </Router>
    

    react-router-dom@6.4 Data APIs

    If you are using the new Data routers you can hit this issue if you attempt to render a header/navbar outside the RouterProvider component. For this you can create a layout route that is part of the routing configuration passed to createBrowserRouter (and other variants).

    Example:

    const AppLayout = () => (
      <>
        <Navbar />
        <Outlet />
      </>
    );
    
    const router = createBrowserRouter(
      createRoutesFromElements(
        <Route element={<AppLayout />}>
          <Route path="/" element={<Home />} />
          <Route path="/experiences" element={<Experiences />} />
        </Route>
      )
    );
    

    ...

    <RouterProvider router={router} />