'useNavigate hook react
I am trying to use useNavigate hook seems that it's not working can't figure out what it needs more current react-router-dom versions that i use. [email protected] -- [email protected] -- [email protected] Current react-router versions. Error: Error: useNavigate may be used only in the context of a Router component
import { BrowserRouter as Router } from 'react-router-dom';
import { useNavigate } from "react-router-dom";
function LandingPage(props) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const auth = getAuth();
const navigate = useNavigate();
async function preventDefault(e) {
e.preventDefault();
console.log(email, password)
try {
const userCredential = await signInWithEmailAndPassword(auth, email, password)
console.log(userCredential.user)
console.log('Authorized')
navigate('/homepage')
} catch (err) {
console.error(err);
alert(err.message);
console.log('Not Authorized')
}
}
return (
<Router>
<div className='wrapper'>
<form>
<h3>Login Here</h3>
<label htmlFor="username">Username</label>
<input type="text" placeholder="Sigh up with email" id="username" onChange={(e) => setEmail(e.target.value)} ></input>
<label htmlFor="password">Password</label>
<input type="password" placeholder="Password" id="password" onChange={(e) => setPassword(e.target.value)}></input>
<button className='button' type="submit" onClick={preventDefault} >Log In</button>
<div className='landingpage-logo'>
<img src={logo} className="landingpage-logo"></img>
</div>
</form>
</div>
</Router>
)
}
export default LandingPage;
import LandingPage from "./components/LandingPage/LandingPage";
import { Route } from 'react-router-dom';
import HomeScreen from "./components/HomeScreen/HomeScreen";
import React from 'react'
import { BrowserRouter as Router } from 'react-router-dom';
function App() {
return (
<Router>
<Route exact path="/">
<LandingPage />
</Route>
<Route path="/homepage">
<HomeScreen />
</Route>
</Router>
);
}
export default App;
Solution 1:[1]
Issues
From what I can tell, there's a Router component wrapping the App component's code, but there appears to be multiple routers. In react-router-dom@6 only a single router/routing context is necessary. Remove all nested Router components.
None of the Route components are being rendered into the Routes component.
Additionally, the Route component API also changed. RRDv6 Route components only render routed content on the element prop. The children prop is only ever used for building nested routes.
Solution
App
Wrap the routes in a Routes component, the spiritual successor to the RRDv5 Switch component. Routes handles the route path matching and rendering of routed content.
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/homepage" element={<HomeScreen />} />
</Routes>
</Router>
);
}
LandingPage
Remove the extraneous router in LandingPage component. It is also more common to use the form element's onSubmit handler to submit a form than an onClick handler on the submit button.
import { useNavigate } from "react-router-dom";
function LandingPage(props) {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const auth = getAuth();
const navigate = useNavigate();
async function preventDefault(e) {
e.preventDefault();
try {
const userCredential = await signInWithEmailAndPassword(
auth, email, password
);
navigate('/homepage');
} catch (err) {
console.error(err);
alert(err.message);
console.log('Not Authorized');
}
}
return (
<div className='wrapper'>
<form onSubmit={preventDefault}>
<h3>Login Here</h3>
<label htmlFor="username">Username</label>
<input
type="text"
placeholder="Sigh up with email"
id="username"
onChange={(e) => setEmail(e.target.value)}
/>
<label htmlFor="password">Password</label>
<input
type="password"
placeholder="Password"
id="password"
onChange={(e) => setPassword(e.target.value)}
/>
<button className='button' type="submit" >Log In</button>
<div className='landingpage-logo'>
<img src={logo} className="landingpage-logo"></img>
</div>
</form>
</div>
);
}
Solution 2:[2]
I'm not 100% sure this is the issue, but I believe your LandingPage does not have access to the Routes context because your Routes in your App are defined incorrectly:
You can define which element the route has to render by using the element prop.
<Route path="/" element={<LandingPage />} />
The children of a Route in react-router 6 are reserved for defining child routes:
<Route path="albums" element={<AlbumsPage />}>
<Route path=":id" element={<AlbumPage />} />
<Route path="add" element={<CreateAlbumPage />} />
</Route>
You can also remove the <Routes /> component in your LandingPage.
Thirdly, the exact prop no longer exists on a <Route /> in react-router 6. You can safely remove it. react-router is smart enough to know which route to render nowadays.
For more information on how to migrate from react-router 5 to react-router 6. Please refer to: https://reactrouter.com/docs/en/v6/upgrading/v5
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Drew Reese |
| Solution 2 | Luze |
