In this post we'll learn about dynamic routes in React which includes how to set route parameters and how to fetch the route parameters.
Why dynamic routing in React
It's a very common requirement in web applications to add a route parameter to the URL based on user input or based on some events. For example, you display list of user names and you show the details of the user whose name is clicked and for that you want to pass userId as a route parameter by appending it to the path- /users/1 or /users/2 and so on based on the clicked user.
It is practically impossible to create static routes by having hard coded values in above mentioned scenario as the number of user records may vary. In such scenarios you will create dynamic routes by having a dynamic segment in your route path that acts as a placeholder for the actual value passed.
How to create dynamic route using react-router
To create a dynamic route that has a route parameter, specify the dynamic segment by prefixing it with a colon. So, the route definition will be in the following form
/route/:routeparam
For example, if you want to create a dynamic path by adding userID of the selected user then such a dynamic route can be defined as-
{path: "/users/:userId", element: <UserDetails/>}
If there is a path segment starting with ":" then it becomes a dynamic segment. In our example ":/userId" is the dynamic segment and it can match any value for this specific segment. Any URL like /users/1, /users/2, users/100 will be matched by this path pattern ("/users/:userId") and use the component UserDetails.
You can also have multiple dynamic segments in one route path- /route/:param1/:param2/:param3
How to retrieve route parameters
When a dynamic route matches the URL, the dynamic segment will be parsed from the URL and provided as params. There is
a useParams()
hook in react-router-dom that can be used to get values of dynamic segments in route path. The useParams()
hook returns an object of key/value pairs of the route parameters from the current URL that were matched by the
<Route path>.
For example if /users/100 matches the route path /users/:userId then useParams() hook will return an object as {userId:100}
You can get the whole object initially
const params = useParams();
And then get the specific route parameter when required.
params.userId
Or you can use object destructuring to get the userId param from the URL
let { userId } = useParams();
Dynamic routing ReactJS example
In the example we display a page with list of user names using Users
Component. For the user's name that is
clicked user details are displayed using UserDetails
component. Dynamic routing is used here to pass userId
as route parameter.
Route Definition
src\components\Routes\route.js
import { createBrowserRouter } from "react-router-dom"; import About from "./About"; import ErrorPage from "./ErrorPage"; import Home from "./Home"; import Navigation from "./Navigation"; import UserDetails from "./UserDetails"; import Users from "./Users"; export const router = createBrowserRouter([ {path: "/", element: <Navigation />, errorElement: <ErrorPage />, children: [ {index: true, element: <Home /> }, {path: "/users", element: <Users />}, {path: "/users/:userId", element: <UserDetails/>}, {path: "about", element: <About />} ] }, ])
Notice the path with dynamic segment- {path: "/users/:userId", element: <UserDetails/>}
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;
Navigation Menu
src\components\Routes\Navigation.js
import { NavLink, Outlet } from "react-router-dom" import "./navigation.css"; const Navigation = () => { 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"> <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> </div> </nav> <div className="container"> <div className="row mt-2"> <div className="col-xs-12"> <Outlet /> </div> </div> </div> </> ); } export default Navigation;
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; }
Components
Two components that we need for user are Users
and UserDetail
.
src\components\Routes\Users.js
import { Link } from "react-router-dom" export const DUMMY_USERS = [ {id: 1, name: "Ram", age: 23}, {id: 2, name: "Namita", age: 25}, {id: 3, name: "Varun", age: 32}, {id: 4, name: "Leo", age: 28}, {id: 5, name: "Melissa", age: 27}, ] const Users = () => { return( <> <div className= "row"> <div className="col-sm-4"> <h2>Users</h2> <ul className="list-group"> {DUMMY_USERS.map(user =><li className="list-group-item" key={user.id}> <Link to={`/users/${user.id.toString()}`}>{user.name}</Link></li> )} </ul> </div> </div> </> ) } export default Users;
Some points to note here are-
- Bootstrap is used here for styling.
- In the code a hardcoded array holding user objects is created named DUMMY_USERS.
- Note how links are created for each user name while looping the user array
<Link to={`/users/${user.id.toString()}`}>{user.name}</Link>
After “/users”, id is appended as another path segment. - When user name is clicked, path is matched by the “/users/:userId” route and UserDetails component is used for rendering.
src\components\Routes\UserDetails.js
import { useParams } from "react-router-dom" import { DUMMY_USERS } from "./Users" const UserDetails = () => { const params = useParams(); // Find the passed ID in the DUMMY_USERS array // converting params.userId to number const user = DUMMY_USERS.find(user => user.id === +params.userId) return ( <> <h2>User Details</h2> <div className="row"> <div className="col-xs-6"> <span>User Name: </span>{user.name} </div> </div> <div className="row"> <div className="col-xs-6"> <span>Age: </span>{user.age} </div> </div> </> ) } export default UserDetails;
Some points to note here are-
- useParams() hook is used here to get the value of the dynamic segment.
- User whose details are to be displayed is then searched in the array using the passed id.
Please refer this post- https://www.knpcode.com/2023/10/setting-error-page-react-router.html to get code of other components like ErrorPage, Home. About.
When Users menu is clicked
Clicking on user name takes to the User details page with details displayed for the user name that was clicked
Nested routes provide a better way to do the same thing. check this post- Nested Route in React
That's all for the topic Dynamic Route in React. If something is missing or you have something to share about the topic please write a comment.
You may also like
- React Router - NavLink in react-router-dom
- Index Route in React Router
- Setting Error Page (404 Page) in React Router
- React Form Using Formik's useFormik() Hook
- React useCallback Hook With Examples
- Java Program to Find Maximum And Minimum Number in a Matrix
- Fail-fast And Fail-safe Iterators in Java
- Life Cycle of a Thread (Thread States) in Java
- Static Method Overloading And Overriding in Java
- Spring Boot + Data JPA + Oracle One to Many Example
No comments:
Post a Comment