How To Use URL Parameters In React Router
React
18/06/2019
When it comes to routing in any type of application, you will always come across two types: static and dynamic routing. Static routes are what most people are familiar with when they start out. These are predetermined routes such as /home
or /about/history
. On the other hand, your dynamic routes are determined as your app is rendering. This provides a number of advantages over static routing, which I will get into later on. Moreover, this tutorial will be specifically focusing on responsive routing, that is, how to use URL parameters in React Router.
New to React Router and need an introduction instead? Check out my article here to get started!
URL parameters explained
So what are URL or route parameters exactly? Well, let's imagine you are selling products on your website and each product has its own product page. How would go about programming this? Hard-code a product page for each product? Well, maybe if you have 1 or 2, but imagine you have 100 or more... that might not be the best idea. 😰
Rather, you should keep things DRY (Don't Repeat Yourself) and create a single product page that changes its displayed information depending on which product a user is currently looking at. And how would we do this? Well, with the use dynamic routing, i.e. responsive routing!
Responsive routing let's us use variables in our routes that can take on any kind string
value. In our responsive route, we distinguish a route parameter or variable by placing :
in front of it. For instance, the dynamic route /product/:id
can now take the values /product/1
or /product/laptop_4
. From these routes, we could then extract the product ID, retrieve any data related to that id from a database and consequently display it on our page.
On a side note: the end of a route parameter can be marked by a /
. Thus, id
would be valid parameter in /product/:id/price
Setting up responsive routes
Alright, it's time to code ladies and gents! 👩💻Below we have a small example of 2 routes with corresponding components. Nothing fancy here...
import React from 'react';import { Route, NavLink } from 'react-router-dom';
function Product() { return ( <div>This is our lovely product page!</div> );}
function HomePage() { return ( <div>Welcome to Chunk Bytes!</div> );}
function App() { return ( <div className="App"> <header> <nav> <ul> <li><NavLink to="/">Home</NavLink></li> <li><NavLink to="/product">Product</NavLink></li> </ul> </nav> </header> <div> <Route exact path="/" component={HomePage} /> <Route path="/product" component={Product} /> </div> </div> );}
export default App;
Let's make our product page a bit more dynamic with the following changes. First, let's add a parameter to our product route with path="/product/:id"
. Next, let's create two NavLink
s, each pointing to two different products.
// Removing the regular product page<li><NavLink to="/product">Product</NavLink></li>
// Adding two new NavLinks<li><NavLink to="/product/laptop1">Laptop</NavLink></li><li><NavLink to="/product/car1">Car</NavLink></li>
With these simple steps, we already created a responsive route. Hooray! 😋 But of course, we're not done yet! 😤 Next, we need to extract our product IDs from the route, so our Product
component knows which product information to retrieve and render. So how do we retrieve this information?
Retrieving URL parameter information
We all know that React components automatically receive a props
parameter (I hope you do... 😳). This is also where we can find our route parameter value. Let's console.log
our component's props
and see what it has to offer.
As we can see, props
has several properties. However, there's one in particular that is of interest to us: match
. This in turn has another property called params
that actually contains the value we are looking for. Alright! So let's make some final changes to our code before we wrap things up.
function Product({ match }) { return ( <div> This is our lovely product page! You are currently viewing {match.params.id} </div> );}
Instead accessing our route parameter value with props.match.params.id
, we can do some destructuring with { match }
. You could even destructure a layer deeper to keep things simpler, e.g. { match: { params }}
. Destructur-...ception? 🤨
A teeny-tiny gotcha
If you're rendering your component in a route using the render
props, e.g. <Route path="/product/:id" render={() => <Product />} />
, make sure to actually pass the props
into your component as follows: render={(props) => <Product {...props} />} />
. I've done this mistake myself 😬 and I've seen many others do it. If you don't, you will see errors such as TypeError: match.params.id is undefined
.