Parameterized Routing and Query Strings with React Router
With the basics in place, this lesson is all about extending the Admin Console with parameterized routing and query strings.
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Beginner's Guide to Real World React course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Beginner's Guide to Real World React, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

[00:00 - 00:12] Lesson 5 - Extending the Admin Console app You should be pretty happy with yourself at this point. Not only have we built a realistic admin console using React and some of its clever features, we've also fitted a complete routing system with working navigation.
[00:13 - 00:23] In this lesson we're going to extend and augment the existing console with a few additions. A data list of users that we'll use to dynamically populate the existing users component and a new edit user component.
[00:24 - 00:32] Parameterized dynamic routing that will plug a specific user from our data list . A mechanism to handle query string parameters which are commonly needed in most navigation systems.
[00:33 - 00:57] Let's dive right in and edit our project back in VS Code. Ultimately we want to replace the static hard-coded user data in the users.jsx file with dynamically generated data. This will simulate a realistic app where we may have fetched it from an API or otherwise loaded it from an external source. Create a new folder called data under the source folder and in this folder create a new file called users.json.
[00:58 - 01:16] Unsurprisingly we're going to populate this file with some JSON data, namely an array of user objects. Nothing tricky here, just some regular JS objects representing individual users with properties like name, email and department. The entire JSON file for our users should look like this.
[01:17 - 02:05] The current user's component contains a static HTML table with some user data hard-coded in it. Let's change this to simulate a realistic fetching of some data and dynamically map some user data into the existing table. What's more we're going to add a new column to the table actions. In here we'll be placing a button that will allow us to click through into the editing component that we'll build out later on. Because we want to use a button that directs the user to another URL we'll bring in the link component from ReactRue to DOM. We'll also need to bring in the user data from the users.json file we just created so we'll do that here too. We're going to outline a single helper function here, getEditTime. This is a really simple function that creates a new data object and then crafts a single return string from the various data functions.
[02:06 - 02:25] The return string represents the current time. We'll be using this function to provide us with an edit time in our table's action links and that will be passed to the routing system as a query string parameter value. Now we need to update the JSX. We'll need to make three edits here. First we're going to remove all of the existing table data, everything inside of the T-body tag.
[02:26 - 02:39] Next we'll add a new header row to our table and name it actions. And the final edit involves adding a new body contents for the table which will look like this.
[02:40 - 03:44] It looks the same as any single row from the hard coded version but this time we're outputting each row as a result of the map function iterating over our users that we brought in as part of the import section. Notice that we've replaced the static strings with their dynamic counterparts from each user data object. We've also added an additional TD element here too that represents our actions column data. In this case it's a link component. We're building up a dynamic URL path to pass to the link component which will end up looking something like this. Users /1 and then an edited value /users /2 edited and then say a time value / users /3 and an edited query string value and so on. We haven't defined any route to handle this type of URL path just yet but we'll discuss that later in the lesson. For now it's enough to know that we're generating a number of similar URL paths each with a different user ID value appended with a query string parameter edited, the value of which is set to the current time returned from our helper function. If you followed the amendments above your completed component should now look like this.
[03:45 - 05:01] Before we update our routes.js file we need to create a component to handle the routes that are created dynamically in our users component. They'll be in the format /users / user id, query string edited equals and then a time value. The query string path has no effect on the routing it's just a series of values that are past as part of the URL. With the query string taken out we can write the URL like this /users /callonid. This is a parameterized URL where the call on id value is unknown until it is requested but we want to match a URL path that looks like this ahead of time. In our case when a user visits a URL that looks like /users /123 it's going to be handled by the edit user component that we're going to build now. Create a new file in the components folder called edit user.jsx and let's get editing. Starting with the import at the top of the file they'll look like this. Aside from the ever present react we're pulling in use location which we've seen before and another hook from ReactRooter use params. The use params hook provided by ReactRooter returns a key value paired object of all the parameters supplied to the route.
[05:02 - 05:39] You can loop through them as with any regular JavaScript object or use the destructuring syntax to grab specific key value pairs as we're going to do in a moment. We're also pulling in our users JSON data from the users.js and file. Onto our helper functions. Even though the use location hook gives us easy access to any query string value via its .search property the query string is returned in its raw rather ugly and unhelpful state something like this. Question mark item 1 equals xyz and item 2 equals abc. In order to get a specific value from this jumble of characters we'll create a helper function get qs value and it'll look like this.
[05:40 - 05:59] The get qs value function accepts two parameters query string and a search term both of which are strings. The job of this function is to look at the query string value that we pass it break it into chunks of key values and find a match against the search term parameter. Now we'll define the default export for the component as follows.
[06:00 - 06:12] With that in place we need to add some variables to kick things off. We're using the use location hook and stuffing it into a params variable.
[06:13 - 06:23] Next we're using the use params hook and grabbing the id value from the URLs parameters. Remember the URL users /123? Well the id part will be returned to us as 123.
[06:24 - 06:38] Finally we need to find the specific user information that the URL we're viewing requires. To do that we search through our users array using the array.find method matching the user.id value against the id value from the root parameter of the same name.
[06:39 - 06:54] If we don't find one we just pick the first user from the bunch. Note you probably wouldn't do this in a real app you'd most likely show some sort of error message to the visitor. For our purposes however it's enough to displace something if the id parameter supplied doesn't match any of our user list.
[06:55 - 08:09] Finally we need to outline some JSX for the UI. We have a series of simple labels with html inputs whose values are set to relevant properties of the selected user object. The main point of note here is that the h2 element contains information about when this user was last edited. Notice how we're using the getqs value function with the params.search value to grab the edited query string value that will be passed to the root in the URL. This value is still just mocked of course as we saw in the user's component but it illustrates how to easily grab query string values from the root information using React Router and the hooks it provides. With all the code added to our new edit user component it should look like this. So we've got a nice new dynamic component users and a component that will handle our parameterized roots. However all of that is for nothing if we don't update our list of roots. So open up the root.js file and believe it or not because of all our hard work in the last lesson we have very little here to do to wire up our new root. We're going to add a new import that brings our edit user component in so we'll do import edit user from components edit user.
[08:10 - 08:47] And the last thing to do is to create a new routing object under the /users section. The name for the new menu item will be edit user and notice that we need the sub URL to just contain the parameterized part which is /colonid. We'll use the newly the terminal and run imported edit user component for this root and save the file. And that's it, really. We don't need to update the app.js file with a new root because that's all handled for us programmatically thanks to the work we carried the yarn start command.
[08:48 - 09:06] Everything should work much as it did before. This time around however when we head to the users URL we'll see our user tables now populated from the JSON data in the users.json file and we have a shiny new edit button.
[09:07 - 09:40] Click on any of the edit buttons and notice the new URL that's updated in the browser's address bar. It'll contain a particular user ID and you should see the correct user data being populated in our mock edit form fields. And that's it for another module. We've learned a lot about how to add routing into React app using the popular React router library. We've covered basic routing and more complex topics such as parameterized routing and query strings. I look forward to seeing you in the next module as we continue our React journey.