Filtering Data with React Routing

If you have a huge list of data on your website, you should expect it to be really hard for the users to find specific piece of information they’re looking for without special tools such as filtering.

Let’s say you visit online shopping site to buy a specific branded product, assume there is no filter option to see only the products list of the brand which you wish to purchase imagine how difficult it could be to check each product to see which brand it belongs to.

In this article I will demonstrate how to add filtering to your React application using React Router.

Image for post
React Router is a good library to implement robust filtering

Filtering at GRAD4

At GRAD4 we started to experience this need of having filtering capabilities for our marketplace after our launch as the list of item (request for quotation) being displayed was becoming unmanageable.

We identified that the users (suppliers) were having hard time to find quotations and we discovered that they were mostly looking at a particular process (i.e. CNC, sheet metal or welded assembly) to know what might be of interest for them.

We also realized that the users wanted this filtering to be remembered in their preference as their interest in particular process didn’t fluctuate very much over time.

This led to the following plan:

  • User should be able to filter the marketplace by the three process available.
  • This information should be stored in the local storage to be remembered.

We will go through how we solved this at GRAD4 for our custom parts manufacturing marketplace using React Routing.

Image for post
To make efficient bids, the manufacturer needs to know what request for quotation is interesting for them via filtering.

Table of Content

  • Filters Overall Behavior
  • Main Filter Component
  • handleChange
  • React Router and useEffect
  • Conclusion

Marketplace Filtering Overall Behavior

Image for post
Marketplace filtering in action

As we can see from the GIF above we have the following component of interest:

  • the marketplace listing which hold the information of all request for quotations.
  • the filter bar which offer the option of filtering by 3 process. Note that if you select all filtering or none it will show the full marketplace.
  • The url bar that is changing dynamically depending on what box is checked.

The logic is pretty simple, it’s the query string in the URL that dictate what should be seen in the marketplace. This means that if we have:

  • marketplace?procede=Usinage CNC : we will be able to see CNC machining parts
  • marketplace?procede=Métal en feuille :we will see the sheet metal parts
  • marketplace?procede=Mécanosoudé : we will see the welded assembly parts

We can even combine them using & in order to show more than one process.

What would happen if we check a box and then try to navigate to /marketplace ?

Image for post

Doing so will route us back to the URL that is consistent with the filtering selected, because we are saving the information about the filtering into local storage. This way when the user navigate back into the marketplace, the proper marketplace filtering will already be in place.

Finally let’s check out what would happen if our user log off and then log back on at some point:

Image for post
Login off doesn’t affect the filtering selection in a previous session

One of the strength and most important use case of localstorage is remembering information between session. This comes in very handy in this particular case as the user will always have a consistent user experience across session inside the marketplace!

Let’s peak under the hood!

Main Filter Component

The main component of interest in the filtering is called ProcessFiltersBody

It’s a functional component that return the following: return statement

The first thing to realize is that it is iterating over the processTypes which is defined earlier and look like this:

const processTypes = [
{ id: 1, type: t("machining_CNC") },
{ id: 2, type: t("sheet_metal") },
{ id: 3, type: t("welded_mechanic") },

The first part of each mapping is simply setting up the style of the checkbox whether they are selected or not, but it gives us a great hint that information inside localstorage is important for this component to work!

className={`c-group-switch ${
localStorage &&
JSON.parse(localStorage.getItem("selectedFilters")) &&
? "c-checkbox-active"
: "c-checkbox-inactive"

The checkbox are also very simple and become check or uncheck depending if the information of local storage includes their value. The part that is important is


which will trigger the logic that will modify the localstorage and affect the routing of the marketplace.


The handleChange function is a pretty standard event listener for the checkbox and look like this: used in the ProcessFilterBody component

Four things are happening in the handleChange:

  1. A list of selectedFilter is created by grabbing what is already selected in the state and modifying the target filter value to be the value of the event (i.e. either is true or false).
  2. The localstorage value of selectedFilters is updated using the list created in #1.
  3. A dispatch of the setSelectedFilters action is triggered to update the state on which filters are selected.
  4. The usage of the functionality is tracked so that we can understand how our users are using it (take a look at our previous blog post on the subject!)

Wait…Where does React Router comes in?

React Router and useEffect

React Router main purpose in a frontend application is to add navigation logic to the user interface. It helps shows the right component by pattern matching the URL.

In this particular scenario, a naive way of using React Router would be to give props back to the Marketplace components that will help selectively show the right item for a given process. However, this can rapidly become messy and error prone.

Instead the implementation we used in our application was to use the history that is provided by react-router-dom to figure out the URL we were at and to check if we needed to look at the localstorage or not. Bundling this logic into the useEffect and listening to particular change give the desired behavior:

There is three useEffect being used here, let’s break them down:

The first useEffect main purpose is to fetch the active request for quotation that match the URL:

To do this we use matchPath from ReactRouter and the location object. After building the right query for the API, we can safely dispatch a fetch of the active request for quotation matching our URL location. This useEffect watches for change in the selectedProcessFilters which we manipulated in the handleChange.

The second useEffect is very straightforward. Using the built-in parameter search in the location object provided to us by React Router we can check if we need to set the filters from the URL:

To do so we watch for any pathname change. However, like we will see in the next useEffect, if the localstorage information will take precedence.

This last useEffect will override the previous one and is constantly being fired up on any change happening inside the ProcessFiltersBody component. It will only act however if the localStorage.selectedFilters is set. After having extracted the information from the storage it will then go ahead and call the setSelectedFilters function on each filter to set the right checked value. This final action will then change the state and render only the request for quotation with the right process checked to true.

There you have it! A full-blown filtering component which is able to remember the user preference using React-Router! 🎆


In this article we covered data filtering, how it can be implemented and how to use it best. Nevertheless, only 16% of e-commerce websites appear to be using filters reasonably good (as seen here).

The customers of e-commerce platform without any filtering capabilities are frustrated by this and do end up simply searching for the product they want on Google instead of the platform itself. This is disastrous for customer retention as they are highly likely to get lost to the competition.

The customers of the other 84% can feel the effect of that such lack of filtering, as they tend to simply search for the product they want in Google and not on the platform itself, and a noticeable amount of customers might get lost to the competitors.

Setting filtering correctly isn’t always straightforward though. Along with the technical details that affect the filtering performance, there is another thing important to keep in mind: the customer behavior. Being able to understand how the customer behave on the website is key to be able to help him use your platform effectively (I have another blog post on behavior tracking check it out!).

Online customers notoriously don’t always know what they want, so the whole process of understanding the customer is a never-ending journey of learning from the customer about the customer. However, to delight your user and make sure that they can use your platform at its full potential this continuous learning activity should be part of your every day processes.

About the author

SriCharani Linga is a senior frontend developer at GRAD4 having 6 years of experience in web development with various web technologies React, Angular and Javascript as primary skill set, her main responsibilities at GRAD4 are features development, creating rich UI, ensuring the quality of deliverables and supporting the frontend team. She has profound working experience in different domains in her past including e-commerce and HR domain in both India and Canada. She has a bachelors degree from JNTU in electronics and communication engineering. More importantly, she is an excellent mentor and is a natural technical leader.

An article by Sri Linga and Yacine Mahdid

Leave a Reply

Your email address will not be published. Required fields are marked *

Utilisez le formulaire
ci-dessous pour nous écrire

Submit my application

Filtering Data with React Routing