Dynamically Loading Material-UI Icons Using React Router Query Params

Know how to implement query params in your next React Router app

Jon Middaugh
Better Programming

--

Aerial view of road
Photo by Steve Medwin on Unsplash.

The purpose of this tutorial is to demonstrate how to use query params in React Router, including using nested routes. However, instead of a boring how-to, I created a tutorial that includes:

  • Dynamically loading Material-UI (MUI) icons.
  • Using Material-UI Buttons as React Router Links.
  • Programmatically setting the route using the useHistory React Router Hook.
  • Extracting query params using the useLocation React Router Hook.

In this demo, we will build an app that takes a user-input MUI icon name, routes to appropriate components with the icon name as a query param (because we’re demoing that), extracts the icon name from the URL, and dynamically imports just that icon from @material-ui/icons.

I believe knowledge sticks better when something useful is built with it. Let’s get to coding!

Note: There are minor differences between using query params and URL params in React Router. CodeSandboxes for both query param and URL param methods are in the Resources section.

App Layout and Code Architecture

MUI Icon previewer

The app is simple: a side drawer that contains a link to the /home route and a <main> element where the routing controls what is displayed. Within the <main> element, there are three components that get swapped out: Home, IconRenderer, and IconDetails.

From the URL, IconRenderer (/previewicon) looks to be a parent of IconDetails (/previewicon/details). However, they are sibling elements in terms of app architecture.

App.js code

I’ll focus on the React Router code:

The app is wrapped in <BrowserRouter>.

Within that, <Switch> is used to swap out what component is rendered in the JSX. It is essentially a JavaScript switch statement for React Router where the case is based on the URL.

Interestingly, I had to set two Route components for <Home> since I wanted both / and /home to render the <Home> component. Another technique would be <Route exact path={“/” | “/home”} component={Home} />, but it wasn’t playing well with the child routes. Also, the / route must have the exact flag set. This means that the route will only match if the URL is exactly /. Without exact, all URLs would route to the <Home> component.

Home.js code

The <Home> component contains an MUI TextField and Button. There are two items of particular interest:

  • The useHistory Hook — I created const history = useHistory(); and then used it to programmatically update the URL when a user presses enter after typing in the TextField:
onKeyPress={(e) => {
if (e.key === "Enter") {
history.push(`/previewicon?iconName=${enteredValue}`);
}
}}
  • The MUI Button containing a React Router Link. The component param contains a React Router Link — not a Material-UI Link component.

IconRenderer.js code

<IconRenderer> extracts the parameter from the URL. It then uses useState, useRef, and an async function to dynamically load the icon according to what the user input in the <Home> component. After this, it renders the icon.

Rendered icon

The code for extracting a value from query params is slightly different (and more verbose) than for extracting URL params:

function useQuery() {
return new URLSearchParams(useLocation().search);
}
let query = useQuery();
const iconName = query.get("iconName");

This code uses the useLocation Hook from React Router.

URL param extraction (if you want to use that instead):

const iconName = props.match.params.iconname;

The async function is in a separate util file since it is shared by two components:

Simply pass in the ref, iconName (originally extracted from the URL), and a loading callback.

IconDetails.js code

Admittedly, <IconDetails> is a bit of a contrived example. I simply wanted to demo how to pass query params to child routes.

<IconDetails> renders the icon in several different color schemes:

Icon in different color schemes

I found it easy to use query params in child components. The URL params method was a little more difficult. Ultimately, it comes down to making sure your URLs have appropriate /, :, and other syntax. Here’s an example of what the child URL param syntax looks like (from Home.js):

<Route
exact
path={"/iconpreviewer/details/:iconname"}
component={IconDetails}
/>

In IconDetail.js, the icon with colors was mapped like so:

Wrapping Up

Both query params and URL params can get the job done. My biggest point of frustration was simply my own errors in getting the Route (path) and Link (to) syntax correct.

Walking through a tutorial like this will give you confidence that you can make React Router work for your apps too.

--

--

I have been: individual contributor | tech lead | manager | JS boot camp teacher | community college instructor.