In this post we'll see how to navigate programmatically in React routing using useNavigate()
hook.
useNavigate() hook
The useNavigate hook is part of the react-router-dom package which returns a function that lets you navigate programmatically.
const navigate = useNavigate();
Here navigate is the returned function.
Using it you can navigate programmatically, for example going to the Home page-
navigate("/home");
You can also pass an optional second options argument.
For example, if you want to navigate relative to path rather than route hierarchy (which is default).
navigate("..", { relative: "path" });
This will navigate up one level in the path, instead of one level in the Route hierarchy.
You can also pass a delta, which is essentially a number passed to go back and forward in the history stack.
navigate(-1);is equivalent to hitting the browser's back button
navigate(1);is equivalent to hitting the browser's forward button
React Router useNavigate hook example
In this example we'll create a navigation with login button and the following functionality.
- When login button is clicked user should be navigated to login page.
- Login button should also change to Logout button.
- On successful login user should be navigated to Users page.
- On clicking Logout button user should be navigated to login screen and old credentials should be cleared.
Login page on click of Login button.
After successful login change to Logout
Navigation Page
src\components\Routes\Navigation.js
import { NavLink, Outlet } from "react-router-dom" import "./navigation.css"; import { useNavigate } from "react-router-dom"; const Navigation = () => { const navigate = useNavigate(); const showAuthButton = () => { if (sessionStorage.getItem("authenticated")){ return <button className="btn btn-light ms-3" onClick={handleLogoutClick}>Logout</button> }else{ return <button className="btn btn-light ms-3" onClick={handleLoginClick}>Login</button> } } const handleLogoutClick = () => { // clear the user credentials sessionStorage.clear(); navigate("/login"); } const handleLoginClick = () => { navigate("/login"); } 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="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span className="navbar-toggler-icon"></span> </button> <div className="collapse navbar-collapse" id="navbarNav"> <ul className="navbar-nav me-auto"> <li className="nav-item"> <NavLink to="/" className={({ isActive }) => isActive ? "active" :""} end > Home </NavLink> </li> <li className="nav-item"> <NavLink to="/users" className={({ isActive }) => isActive ? "active" :""} > Users </NavLink> </li> <li className="nav-item"> <NavLink to="/about" className={({ isActive }) => isActive ? "active" :""} > About </NavLink> </li> </ul> <div className="d-flex"> {showAuthButton()} </div> </div> </div> </nav> <div className="container"> <div className="row mt-2"> <div className="col-xs-12"> <Outlet /> </div> </div> </div> </> ); } export default Navigation;
One addition to note here is the showAuthButton()
function which shows either the Login button or the
Logout button based on whether sessionStorage has the "authenticated" value set as true or not. The "authenticated" value
is set as true when the user successfully logins (Done in Login.js).
useNavigate() hook is used to get the function. That is then used in the functions associated with the click event of the Login and Logout button to navigate to "/login".
src\components\Routes\navigation.css
#menu a:link, #menu a:visited { color: gray; } #menu a:hover { color: white; } #menu a.active { color:#ebecf0; } #menu a { text-decoration: none; } #menu ul { gap: 1rem; }
Route Definition
src\components\Routes\route.js
import { createBrowserRouter } from "react-router-dom"; import About from "./About"; import Home from "./Home"; import Login from "./Login"; import Navigation from "./Navigation"; import Users from "./Users"; export const router = createBrowserRouter([ {path: "/", element: <Navigation />, children: [ {index: true, element: <Home /> }, {path: "login", element: <Login />}, {path: "users", element: <Users />}, {path: "about", element: <About />} ] }, ])
Providing the routes
Provide the route definition to your application using the <RouteProvider> component.
import { RouterProvider } from 'react-router-dom'; import { router } from './components/Routes/route'; function App() { return <RouterProvider router={router}></RouterProvider> } export default App;
Login Page
src\components\Routes\Login.js
import { useState } from "react"; import { useNavigate } from "react-router-dom"; const user = { email: "test@test.com", password: "password" }; const Login = () => { const navigate = useNavigate(); const [formField, setState] = useState({ email: '', passwd: '', errors: [] }); const handleInputChange = (event) => { let errors = []; // clear errors if any if (formField.errors.length > 0) { setState((prevState) => ( {...prevState, errors} )); } const value = event.target.value; const name = event.target.name; setState((prevState) => ( {...prevState, [name]: value} )); } const submitHandler = (event) => { event.preventDefault(); let errors = []; //email regular expression pattern const emailRegEx = /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/; let isEmailValid = emailRegEx.test(formField.email.toLowerCase()) if (!isEmailValid) { errors.push("email"); } if(formField.passwd === ""){ errors.push("passwd"); } setState((prevState) => ( {...prevState, errors} )); // If there is error dont submit, return to form if (errors.length > 0) { return false; } else{ // chack if email and password match if(formField.email === user.email && formField.passwd === user.password){ console.log('user found') // set to session storage sessionStorage.setItem("authenticated", true); navigate("/users"); }else{ console.log('user not found') errors.push("auth"); } } } const hasError = (name) => { console.log("haserror " + name + formField.errors.indexOf(name)); return formField.errors.indexOf(name) !== -1; } return ( <div className="card col-5 mt-5 mx-auto"> <div className="card-header bg-info text-white"> <h2>User Login</h2> </div> <div className="card-body"> <form onSubmit={submitHandler}> <div className="mb-3"> <label className="form-label" htmlFor="userEmail">Email</label> <input type="text" className={hasError("email") ? "form-control is-invalid" :"form-control"} placeholder="Enter Email" name="email" id="userEmail" value={formField.email} onChange={handleInputChange} /> <div className={hasError("email") ? "invalid-feedback" : ""}> { hasError("email") ? <span>Please enter valid email</span> : "" } </div> </div> <div className="mb-2"> <label className="form-label" htmlFor="userPassword">Password</label> <input type="password" className={hasError("passwd") ? "form-control is-invalid" :"form-control"} placeholder="Enter Password" name="passwd" id="userPassword" value={formField.passwd} onChange={handleInputChange}/> <div className={hasError("passwd") ? "invalid-feedback" : ""}> { hasError("passwd") ? <span>Please enter password</span> : "" } </div> </div> <div> { hasError("auth") ? <span style={{color: "red"}}>Email and/or Password not correct</span> : "" } </div> <button type="submit" className="btn btn-primary mt-1">Submit</button> </form> </div> </div> ) } export default Login;
Important points to note here are-
- For simplicity user information is hardcoded and that is matched for the correct credentials.
- When the form is submitted, after checking for errors, entered information is compared with the hardcoded user
information. If matches then using navigate, navigation is done to Users page. Value of “authenticated” is also set
as true in sessionStorage.
if(formField.email === user.email && formField.passwd === user.password){ console.log('user found') // set to session storage sessionStorage.setItem("authenticated", true); navigate("/users"); }
- If user information doesn't match then an error is displayed.
If you need more clarity about the login screen and how validation is done, please refer this post- React Bootstrap Login Form With Validations
Home Page
src\components\Routes\Home.js
const Home = () => { return ( <> <h2>This is Home page</h2> </> ) } export default Home;
Users Page
src\components\Routes\Users.js
const Users = () => { return( <> <h2>This is User page</h2> </> ) } export default Users;
About Page
src\components\Routes\About.js
const About = () => { return <h2>This is a router demo</h2> } export default About;
That's all for the topic React Router Navigating Programmatically Using useNavigate Hook. If something is missing or you have something to share about the topic please write a comment.
You may also like
- Setting Error Page (404 Page) in React Router
- Dynamic Route in React
- Nested Route in React
- Installing Bootstrap in React
- React useRef Hook With Examples
- Java String split() Method
- Java Static Import With Examples
- Heap Sort Java Program
- Python I/O - Open, Read, Write Files
- Spring Boot With JSP Example
No comments:
Post a Comment