The new Cosmic dashboard is now available in private beta 🎉
Get it now →

Search and filter products using React Hooks and a headless CMS

Community Articles
Community Articles Search and filter products using React Hooks and a headless CMS

Pictured above is what we will be building. View the live demo.

Searching and filtering products is a common feature for websites and apps, especially ecommerce. In this article, we will discuss how to build a search and filter feature for products using React. The product data will be queried from a headless CMS (Cosmic) with the UI updated instantly. Bonus: we will talk about how state management is handled using Hooks and API usage optimization with the debounce technique.

You can also follow along with this article on YouTube.

Install template demo content

To get started with this example, install the uNFT Marketplace template which includes the demo content that we will use for the search and filter functionality. Or you can skip this step and just follow along with the code.

  1. Log in to your Cosmic account.
  2. Go to the uNFT Marketplace and click “Select Template”.
  3. Follow the steps to create a new Project and Bucket and import the demo content.
  4. See the demo content now installed in your Bucket.
  5. Go to Products and note the Metafields which contain the data that we will use for our React search / filter feature.

https://imgix.cosmicjs.com/023df770-136a-11ed-b476-13ceb56f12f2-Cosmic-Bucket.png

Create the search / filter React app

To make things easier, we’ve already built a small app with the search / filter feature available on StackBlitz.

StackBlitz

Using the Cosmic API we can filter the product results by search criteria. Now let’s see how it works.

Create the search / filter query

To filter the products in our feature, we will need to send a request to the Cosmic API to get only the products that match the search criteria. To do this, we will use Cosmic Queries.

To create the query, we create an object query with properties that match up with the Object Metadata values that we are searching for like color, price, and categories .

Here is an example with comments to explain what each query property does.

const query = {
  // Find Objects in products Object Type
  "type":"products"
  // Find products with a price greater than or equal to 10 and less than or equal to 100
  "metadata.price":{
    "$gte":10,
    "$lte":100
  },
  // Find products that have the color Blue
  "metadata.color":"Blue",
  // Find products that have the category Sale (uses category Object id)
  "metadata.categories":"627e23f18bb13a000911ea55",
}

After we build our query, we send the query to the Cosmic NPM module using the getObjects method. We use props to limit the response to only the properties we need. Here's an example of what the implementation looks like.

import Cosmic from 'cosmicjs';

const bucket = Cosmic().bucket({
  slug: "YOUR_COSMIC_BUCKET_SLUG",
  read_key: "YOUR_COSMIC_BUCKET_READ_KEY",
});

const params = {
  query,
  props: 'title,slug,metadata,created_at'
}
const data = await bucket.getObjects(params);

Now let’s get into the details about how React handles the UI state updates using Hooks.

React Hooks

React uses one-way data flow, passing data down the component hierarchy from parent to child components. For every search and filter update to the input fields, we are adding state to the React application using the state hook useState.

// App.js
const [search, setSearch] = useState('');
const [{ min, max }, setRangeValues] = useState({ min: '', max: '' });

To display the filtered data on the webpage, we map over the filterResult  array and display the appropriate list of products.

// App.js
<div className={styles.list}>
  {filterResult?.length ? (
    filterResult?.map(product => (
      <Card className={styles.card} item={product} key={product.slug} />
    ))
  ) : (
    <p className={styles.inform}>Try another category!</p>
  )}
</div>

https://imgix.cosmicjs.com/1d1cef10-136a-11ed-b476-13ceb56f12f2-React-search-and-filter-Cosmic.gif

React Custom Hook useDebounce

When the user types something in the input field, the state of the search variable will be updated. To improve the search and filter experience we will create a React Custom Hook useDebounce.

This hook enables a debounce that clears any fast changing value. The debounced value will only reflect the latest value when the useDebounce hook has not been called for the specified time period. When used in conjunction with useEffect, you can ensure that expensive operations like API calls are not executed too frequently.

// utils/hooks/useDebounce.js
import { useState, useEffect } from 'react';

function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);
  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);

  return debouncedValue;
}

export default useDebounce;

The example below allows you to search the Cosmic API and uses useDebounce to prevent API calls from being fired on every keystroke. The goal is to only have the API call fire when the user stops typing, so that we aren't hitting the Cosmic API rapidly.

// App.js
const [search, setSearch] = useState('');

// Debounce search term so that it only gives us latest value
// If search has not been updated within last 500ms, query the Cosmic API
const debouncedSearchTerm = useDebounce(search, 500);

useEffect(() => {
  let isMount = true;

  if (isMount && debouncedSearchTerm?.length) {
    handleFilterDataByParams({
      search: debouncedSearchTerm,
    });
  }

  return () => {
    isMount = false;
  };

}, [debouncedSearchTerm]);

Conclusion

Searching and filtering is a common feature for many websites and apps which can prove challenging to build. But by using the right tools and techniques, building this feature can be made easier and more enjoyable for the end user.

In this article, we showed you how you can use Cosmic Queries, React Hooks, and debounce to create a great search and filter experience. The examples explained in this article are all part of the uNFT Marketplace app template. You can view the full demo here, install the app template in your own Cosmic dashboard, or clone the GitHub repository. To learn more about Cosmic Queries go to the Cosmic documentation.

If you have any questions, you can reach out to us on Twitter, Slack, and subscribe to our YouTube channel.

You may also like


In this tutorial, I’m going to give you an overview of Mux Extension, talk about the benefits of adding Mux to your Cosmic Bucket and show you how to install it to your Bucket in a few clicks.
Why should you migrate your CMS? What's the big deal about Cosmic? This article should answer some questions you have about cosmicJS and what the pros and cons are of using an API-driven Content Management System
Exporting Cosmic-powered data to CSV is easy with this new extension 🚀
In this blog we'll quickstart a React ToDo App using the Cosmic CLI. This is a simple todo application that consumes the Cosmic API and is built using React, Redux, Node.js and Webpack.
Website built using the Next.js Website Boilerplate. Fully responsive down to mobile, SEO ready, includes a contact form and full site search.
Filtering data is one of the most common feature of any data facing application, wheather it's a fron-end app or a back-end application. The Filter function is used to find records in a table or a dataset that meets certain criteria.

Get started with Cosmic

Personal projects are free. Scale up as you grow.
Start building Talk to sales