In this post we'll see how to use useNavigate()
hook in React Router to navigate programmatically between routes in your
application.
useNavigate() hook in React
useNavigate() hook returns a function. You can pass a path to that function to navigate to that path. For example, if you want to navigate from current path to "/dashboard/setting"
const navigate = useNavigate(); navigate("/dashboard/setting");
You can also pass options as second argument to the function. This second argument is an optional object that can include additional configuration settings. Full signature is-
navigate( to: To, options?: { flushSync?: boolean; preventScrollReset?: boolean; relative?: RelativeRoutingType; replace?: boolean; state?: any; viewTransition?: boolean; } )
Explanation of some of the options is as given below-
- preventScrollReset- You can prevent the scroll position from being reset by using { preventScrollReset: true } option.
- relative- When passing path to the navigate function you can pass an absolute path like navigate(“/about”) or a
relative path like navigate('../settings'). The relative option can be set to "route" or "path". By default, relative option
is set to “route” which uses route hierarchy so ".." will remove all path segments of the current route. Which means if you
are currently at /user/account and use
navigate('../settings')
then it will navigate to /settings.
Using relative option as "path" will let you navigate relative to path. Which means if you are currently at /user/account and usenavigate('../settings', { relative: "path" })
then it will go one level up in the current path segment and navigate to /user/settings. - replace- By default replace is false which means navigate adds a new entry to the history stack. Using
{replace:true} option will remove the current entry in the history stack, replacing it with a new one. A use case for
this is if you are navigating to login but doesn't want user to redirect to login page by pressing back button.
navigate('/login', { replace: true });
- state- If you use state to set any value, that will be available on the location object on the next page. In the
target page you can access the state using useLocation() hook.
navigate('/user', { state: { account: 'disable' } });
usinguseLocation().state.account
, in the target page will return value as "disable".
Navigating back and forward in history stack
By using navigate(number) where number can be a positive or negative number you can navigate forward/back (equivalent to pressing forward or back button in the browser). For example-
// back navigate(-1); // forward navigate(1);
useNavigate React example
In the example we'll have UserRegistrationForm component and UserSuccess component. When user clicks the submit button after filling the form properly, user should be navigated to /userSuccess path.
Routing configuration
import { BrowserRouter, Route, Routes } from 'react-router'; import About from './components/routes/About'; import Home from './components/routes/Home'; import NavigationNavLink from './components/routes/NavigationNavLink'; import UserRegistrationForm from './components/routes/UserRegistrationForm'; import UserSuccess from './components/routes/UserSuccess'; function App() { return ( <> <BrowserRouter > <Routes> <Route path="/" element={<NavigationNavLink />}> <Route path="home" element={<Home />} /> <Route path="about" element={<About />} /> <Route path="user" element={<UserRegistrationForm />} /> <Route path="userSuccess" element={<UserSuccess />} /> </Route> </Routes> </BrowserRouter> </> ); } export default App;
Navigation menu
src\components\routes\NavigationNavLink.js
import { NavLink, Outlet } from "react-router"; import "./navigation.css"; const NavigationNavLink = () => { const style = (({ isActive, isPending }) => isPending ? "pending" : isActive ? "active" : "" ); return( <> <nav id="menu" className="navbar navbar-expand-lg bg-dark navbar-dark"> <div className="container-fluid"> <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMenu" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span className="navbar-toggler-icon"></span> </button> <div className="collapse navbar-collapse" id="navbarMenu"> <ul className="navbar-nav"> <li> <NavLink className={style} to="/home"> Home </NavLink> </li> <li> <NavLink className={style} to="/user"> UserRegistration </NavLink> </li> <li> <NavLink className={style} to="/about" > About </NavLink> </li> </ul> </div> </div> </nav> <div className="container row mt-2"> <Outlet /> </div> </> ); } export default NavigationNavLink;
CSS styling for the links
src\components\routes\navigation.css
#menu a:link, #menu a:visited { color: gray; } #menu a:hover { color: white; } #menu a.active { color: #7FFFD4; } #menu a { text-decoration: none; } #menu ul { gap: 1rem; }
Components
src\components\routes\Home.js
const Home = () => { return ( <> <h2>This is home page</h2> </> ) } export default Home;
src\components\routes\About.js
const About = () => { return ( <> <h2>This is about page</h2> </> ); } export default About;
src\components\routes\UserRegistrationForm.js
A simple user registration form with 2 fields name and age.
import { useState } from "react"; import { useNavigate } from "react-router"; const UserRegistrationForm = () => { const [name, setName] = useState(''); const [age, setAge] = useState(''); const [error, setError] = useState(''); const navigate = useNavigate(); const nameChangeHandler = (event) => { const name = event.target.value; const re = /^[A-Za-z]+$/; if (name === "" || re.test(name)) { setName(name); } //setName(); } const ageChangeHandler = (event) => { const age = event.target.value; setAge(age); } const formSubmitHandler = (event) => { event.preventDefault(); if(name === "" || age === "" ){ console.log('error'); setError("Either name or age is not filled"); return false; } //If both fields are filled navigate to UserSuccess navigate("/userSuccess"); } return ( <> {error && <p style={{color:"red"}}>{error}</p>} <form onSubmit={formSubmitHandler}> <label htmlFor="name">Name: </label> <input type="text" id="name" value={name} onChange={nameChangeHandler}></input> <label htmlFor="age">Age: </label> <input type="number" id="age" value={age} onChange={ageChangeHandler}></input> <br /><br /> <button type="submit" >Submit</button> </form> </> ); } export default UserRegistrationForm;
Some points to note here-
- useNavigate() hook is used here to navigate programmatically to another route.
- In the formSubmitHandler function there is a validation to check if both name and age fields have values or not. If yes then navigate to "/userSuccess" path. If not then set the error state and remain in the same registration form.
src\components\routes\UserSuccess.js
const UserSuccess = () => { return( <h3>User registered successfully!</h3> ) } export default UserSuccess;
In UserRegistrationForm
On clicking submit after filling the form
If there is error in the form
That's all for this topic useNavigate in React Router to Navigate Programmatically. If you have any doubt or any suggestions to make please drop a comment. Thanks!
Related Topics
You may also like-
No comments:
Post a Comment