The new Cosmic dashboard is here!
Test drive 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 blog we'll quickstart a React Native Cross-Platform Blog using the Cosmic CLI. This app is three apps in one: Web, iOS and Android app all with content powered by Cosmic. Go to the GitHub repo to see the iOS and Android app share the same React Native codebase.
Salesforce is the world’s leading enterprise CRM application. Zapier gives people internet superpowers by allowing them to connect and automate the apps they use. Using Zapier to connect your Cosmic-powered content with Salesforce is easy and requires zero coding.
This is a quick example to show some of the powerful things you can do with the Cosmic NPM Module. This script will, add a Bucket to your Cosmic account, add an Object Type (Pages) and add a few Pages.
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.
Learn how I built the Twitter Search Extension to search and save Tweets to your Bucket.
Cosmic allows developers to deploy their codebases to the Cosmic App Server for staging, testing and demo purposes, and is now offering new production deployment options available with some of your favorite deployment services.

Get Started with Cosmic

Build personal projects for free. Add your team at unbeatable prices.
Start Building Talk to Sales