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

Viewed 73540

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

10 Answers

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>

in React Route v6 you can solve this giving the route context to your entire App with <BrowserRouter>

This is an complete example of index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { App }  from './components/App/App.jsx';


ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>  //that is the key
      <App />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);

If you are still having problem with this one is because react-router-dom relies on React context to work when try unit testing it. This makes <Link /> or <Route /> obsolete.
Try reading the react-router-dom documentation.

Instead of using

render(<Example />)

that have either or in it, you can try

render(<MemoryRouter>
    <Example />
</MemoryRouter>)

Hope this solve your problem

Links are inside Navbar & Navbar is outside of Router => links are outside of Router => Router will not manage Links

Solution

Move the Navbar into Router section. Example:

<Router>
  <Navbar /> // <===========
  <Routes>
    <Route />
    <Route />
  </Routes>
</Router>

In react-router-dom:6.x and react:18.x, we should use in the following way to resolve the issue

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { App }  from './App.js';

const root = ReactDOM.createRoot(document.getElementById("root"));

root.render(
  <React.StrictMode>
    <Router>  // Router
      <App /> // Application
    </Router>
  </React.StrictMode>
); 

Install in your project React Router v6.

npm install react-router-dom@6 

Then use BrowserRouter in your index.js file, below like this:

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
<React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

React Router v6 this problem common one, you can simply replace "index.js" code. you will got solution-

import React from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';

const container = document.getElementById('root');
const root = createRoot(container);
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

Wrap navbar with BrowserRouter

import { BrowserRouter, Routes, Route } from "react-router-dom";
<BrowserRouter>
    <AppNavBar />
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/wall" element={<WallPost />} />
    </Routes>
  </BrowserRouter>

This is very much an edge case, but in my case it turned out a lib I develop had react-router-dom: 6.0.2 installed and project that uses it v6.3.0

Your links just needs to be within a BrowserRouter component since you use v6 After importing

<BrowserRouter>
    <Link to='page'>
</BrowserRouter>
Related