简体   繁体   中英

React js: Error: useLocation() may be used only in the context of a <Router> component

im using react router v6 and i every time i use initializing for authentication in my main file it shows this error. i cant find a solution in the inte.net for it. i want to render some routes only when there is a user but now it doesnt render anything.

AuthNavigator

 import React, { useState, useEffect } from 'react'; import app from './firebase'; import { Router, Routes, Route } from 'react-router-dom'; import AuthStack from './stacks/AuthStack'; import AppStack from './stacks/AppStack'; import StaticStack from './stacks/StaticStack'; function AuthNavigator() { const [initializing, setInitializing] = useState(true); const [user, setUser] = useState(() => app.auth().currentUser); useEffect(() => { const unsubscribe = app.auth().onAuthStateChanged((user) => { if (user) { setUser(user); } else { setUser(null); } if (initializing) { setInitializing(false); } }); // cleanup subscription return unsubscribe; }, []); if (initializing) return 'Loading....'; return ( <Router> <Routes> <Route path="*" element={<StaticStack />} /> <Route path="auth/*" element={<AuthStack user={user} />} /> <Route path="app/*" element={<AppStack user={user} />} /> </Routes> </Router> ); } export default AuthNavigator;

App.js

 import React from 'react'; import './App.css'; import AuthNavigator from './AuthNavigator'; import { Router } from 'react-router-dom'; function App() { return ( <Router> <AuthNavigator /> </Router> ); } export default App;

Already wrapped in Router?

if your component is already wrapped in a Router. Make sure you are importing useLocation from react-router-dom instead of react-router . this worked for me.

Don't import nor use Routes this component is not exported by 'react-router-dom'

Make sure that your App component in index.js is wrapped with BrowserRouter like this

const app = (
  <Provider store={store}>
      <BrowserRouter>
          <App />
      </BrowserRouter>
  </Provider>
);

I had the same issue. My issue is because of the following reason. I had a Header component which consists of NavLink which is a router component. I placed this Header component inside the App component. My App component was like this:

function App() {
  return(
      <Header/>
      <Router>
        <Routes>
          <Route path="/" element={<Homepage/>}/>
          <Route path="/shop" element={<Shop/>}/>
          <Route path="/signin" element={<Signin/>}/>
        </Routes>
      </Router>
  )
}

In the above App component, I have placed Header component outside of Router. Since in the Header component I have used NavLink which is a Router component caused this error. Then I moved Header component into the Router component then it worked fine. Finally my code looked like this:

function App() {
  return(
      <Router>
        <Header/>
        <Routes>
          <Route path="/" element={<Homepage/>}/>
          <Route path="/shop" element={<Shop/>}/>
          <Route path="/signin" element={<Signin/>}/>
        </Routes>
      </Router>
  )
}

Try the above code from Sebastian Maj:

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

[I have the same error. i'm trying to navigate with my the mouse scroll through my different page. but the web page is still blanc. no error in the console. ][1]

I had the same error coming up from inside a test. The component I was testing contained a NavLink component, and I wasn't rendering a Router in the test. This error disappeared after wrapping my component in question with BrowserRouter .

I had this error because Vite was bundling two copies of the same version of react-router-dom... check the outputted bundle for * React Router DOM and see how many copies there are.

If that's the case, the solution will differ. In my scenario I think it's because I was referencing other local npm packages using file: ... once I switched to a npm workspace that fixed it.

in my case, I faced this error when I used the HOC and context provider and placed my Routing component as the context.provider's child, and export my Provider component by HOC like this:

class Provider extends Component {

render() {
    return (
      <Context.Provider
        value={{
          something: this.state.something
        }}
      >
        <Routing />
      </Context.Provider>
    );
  }
}
export default HOC(Provider)

In case you run into this problem when running a test, don't forget to wrap your import of App in Router as well. My crude example is below.

import { render, screen } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';

import { App } from '../App';

test('renders Box', () => {
  render(
    <BrowserRouter>
      <App />
    </BrowserRouter>
  );
  const boxElement = screen.getByLabelText('box-outline');
  expect(boxElement).toBeInTheDocument();
});

So i fixed like this structure

index.js

import { BrowserRouter } from 'react-router-dom'

<Provider store={store}>
    <BrowserRouter>
        <App />
    </BrowserRouter>
</Provider>

App.js

import { Route, Routes, Navigate } from 'react-router-dom'

<Layout>
  <Routes>
    <Route path="/" element={<Navigate to="/home" />} />
    <Route path="/home" element={<Home />} />
    {...}
    <Route path="*" element={<NotFound />} />
  </Routes>
</Layout>

Layout.js

<Fragment>
  <Header></Header>
  <main className="container">{props.children}</main>
</Fragment>

Header.js

import { Link, NavLink } from 'react-router-dom'

<header className={classes.header}>
<nav>
  <NavLink
    className={(navData) => (navData.isActive ? classes.active : '')}
    to="/search"
  >
    Search
  </NavLink>
</nav>
</header>

App.test.js

import { BrowserRouter } from 'react-router-dom';

it('renders learn react link', async () => {
  render(<BrowserRouter><App /></BrowserRouter>)
  const linkElement = await screen.findByText(/home/i)
  expect(linkElement).toBeInTheDocument()
})

I had this problem when using {useLocation} from 'react-router-dom'

function App() {
  const { pathname, hash, key } = useLocation();
  //function using pathname hash and key

  return(
    <Router>
      <Header/>
      <Routes>
        <Route path="/" element={<Homepage/>}/>
        <Route path="/shop" element={<Shop/>}/>
        <Route path="/signin" element={<Signin/>}/>
      </Routes>
    </Router>
  )
}

throws the same error even with the in the correct place I fixed it by explicitly wrapping the useLocation() within the router

function App() {
  return(
    <Router>
      <Header/>
      <Inner/>
    </Router>
  )
}
function Inner() {
  const { pathname, hash, key } = useLocation();
  //function using pathname hash and key

  return(
    <Routes>
      <Route path="/" element={<Homepage/>}/>
      <Route path="/shop" element={<Shop/>}/>
      <Route path="/signin" element={<Signin/>}/>
    </Routes>
  )
}

im my case, the problem was putting BrowserRouter inside App.js file, solved it by moving this into index.js file and wrapping it around App.js

Former Index.js

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider store={store}>
    <React.StrictMode>
      <PersistGate persistor={persistor} >
        <App/>
      </PersistGate>
    </React.StrictMode>
    </Provider>
  
);
reportWebVitals();

Former App.js

import { BrowserRouter, Routes, Route, useLocation} from "react-router-dom";

const App = () => {
  const {pathname} = useLocation()
  return (
    <div className='app'>
      <BrowserRouter>
          <Routes>
              <Route path='/*' element={<LandingPage />} />           
          </Routes>
       </BrowserRouter> 
    </div>
  );
};
export default App;

New Index.js

import { BrowserRouter } from 'react-router-dom';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider store={store}>
    <React.StrictMode>
      <PersistGate persistor={persistor} >
        <BrowserRouter >
            <App/>
        </BrowserRouter>
      </PersistGate>
    </React.StrictMode>
    </Provider>
  
);
reportWebVitals();

New App.js

import { Routes, Route, useLocation} from "react-router-dom";

const App = () => {
  const {pathname} = useLocation()
  return (
    <div className='app'>
        <Routes>
            <Route path='/*' element={<LandingPage />} />           
            <Route path='/registeration'  element={<Registration />} /> 
        </Routes>
    </div>
  );
};
export default App;

Try this:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM