Building a Debounced Input Component in React with TypeScript
Tags: webdev, programming, react, softwaredevelopment
Published: 2024-04-19 19:35:58

---
title: Building a Debounced Input Component in React with TypeScript
published: true
date: 2024-04-08 11:02:03 UTC
tags: webdevelopment,programming,react,softwaredevelopment
canonical_url: https://antondevtips.com/blog/building-a-debounced-input-component-in-react-with-typescript
---


### Introduction

Let’s explore a web application that fetches data from an API based on the user’s input. Everytime user enters a character in a search input — a request is sent to get filtered data from the API. If we implement an application this way we’ll experience a common performance issue related to rapid state updates.

This is where **debouncing** comes into play. **Debouncing** is a programming practice used to ensure that time-consuming operations are not executed too often. A **debounced input** delays the processing of the input’s keyup event until the user has stopped typing for a given amount of time (often milliseconds or seconds). If the user starts typing again before this time is up, the timer resets. This approach prevents the application from making excessive calls to APIs or performing redundant operations, thus enhancing performance, UI responsiveness and overall user experience.

### Implementing Debounced Input in React with TypeScript

Let’s create a simple debounced input component in React using TypeScript. We’ll use [use-debounce](https://www.npmjs.com/package/use-debounce) NPM package for the **debounce** function:

```jsx
import React, { useState, useEffect } from "react";
import { useDebounce } from "use-debounce";
    
type DebouncedInputProps = {
    value: string;
    onChange: (value: string) => void;
    placeholder?: string;
    delay?: number; // Delay in milliseconds
}
    
export const DebouncedInput: React.FC<DebouncedInputProps>
    = ({ value, onChange, placeholder = '', delay = 250, }) => {
    const [inputValue, setInputValue] = useState(value);

    // Create a debounced value
    const [debouncedValue] = useDebounce(inputValue, delay);

    /**
     * Call the onChange function when a user stops typing
     */
    useEffect(() => {
        onChange(debouncedValue);
    }, [debouncedValue]);

    return (
        <input
            type="text"
            value={inputValue}
            onChange={(e) => setInputValue(e.target.value)}
            placeholder={placeholder}
        />
    );
};
```

Here an input value in the component’s state is updated everytime a user enters a character. But **DebouncedInput** component calls the **onChange** function only when the user stops typing for more than a given delay.

**onChange** function reports a debounced value changes to the parent component. Let’s create a page that utilizes the **DebouncedInput** component to fetch products bases on a user input. First, we need to define some products that will be fetched:

```ts
type Product = {
  id: number,
  title: string
}

const products: Product[] = [
    { id: 1, title: "Samsung Galaxy S24" },
    { id: 2, title: "Samsung Galaxy Fold 4" },
    { id: 3, title: "iPhone 14 pro" },
    { id: 4, title: "One Plus 7" },
    { id: 5, title: "Xiaomi 14 Pro" }
];
```

Now let’s create a SearchPage component.

```jsx
export const SearchPage: React.FC = () => {
    const [filteredProducts, setFilteredProducts] = useState<Product[]>(products);
    
    return (
        <div>
            <h1>Debounced Search Example</h1>
            <DebouncedInput
                value={''}
                onChange={searchProductsAsync}
                placeholder="Type to search..."
                delay={250} // Debounce delay in milliseconds
            />
            <div>
                {filteredProducts.length > 0 ? (
                    <div>
                        {filteredProducts.map(product => (
                            <div key={product.id}>{product.title}</div>
                        ))}
                    </div>
                ) : (
                    <p>No products found.</p>
                )}
            </div>
        </div>
    );
};
```

Here we render a DebouncedInput where the user enters a name of the product to search for. Then we need to call an API to get filtered products.

Here is a function callback for a **DebouncedInput** that fetches products when a user stops typing for 250ms:

```ts
const searchProductsAsync = async (searchText: string) => {
    // Simulating a network request with a delay
    await new Promise(resolve => setTimeout(resolve, 250));

    if (!searchText.trim()) {
        setFilteredProducts(products);
        return;
    }

    const lowercasedFilter = searchText.toLowerCase();
    
    const filteredData = products.filter(p =>
        p.title.toLowerCase().includes(lowercasedFilter)
    );
    
    setFilteredProducts(filteredData);
};
```

This implementation with debounced input prevents our API from being called too often, making the web page more performant and UI more responsive.

### Summary

By implementing a **debounced** input in React, you can significantly enhance the user experience in your applications, especially in scenarios where inputs trigger time-consuming operations like API calls. This example demonstrates the power of **debouncing** in managing efficient state updates and provides a reusable **DebouncedInput** component that can be easily integrated into any React project. A **debounced** input is easy to implement and it not only improves performance but also make user interface more responsive, making it an essential technique in the modern web developer’s toolkit.

Hope you find this blog post useful. Happy coding!

_Originally published at_ [_https://antondevtips.com_](https://antondevtips.com/blog/building-a-debounced-input-component-in-react-with-typescript)_._

### After reading the post consider the following:

- [Subscribe](https://antondevtips.com/blog/building-a-debounced-input-component-in-react-with-typescript#subscribe) **to receive newsletters with the latest blog posts**
- [Download](https://github.com/AntonMartyniuk-DevTips/dev-tips-code/tree/main/frontend/react/debounced-input) **the source code for this post from my** [github](https://github.com/AntonMartyniuk-DevTips/dev-tips-code/tree/main/frontend/react/debounced-input) (available for my sponsors on BuyMeACoffee and Patreon)

If you like my content —  **consider supporting me**

Unlock exclusive access to the source code from the blog posts by joining my **Patreon** and **Buy Me A Coffee** communities!

[![](https://cdn-images-1.medium.com/max/233/1*GSZFx05RDUWr5pn_E9bK8w.png)](https://www.buymeacoffee.com/antonmartyniuk)

[![](https://cdn-images-1.medium.com/max/229/1*8tJk9eYCJrkzoAJw2cILSA.png)](https://www.patreon.com/bePatron?u=73769486)