Debounce Functionality in React Js

Using JavaScript
  • To implement a debounce functionality in React, you can follow these steps. The debounce function will limit the number of API calls made by delaying the execution until a certain amount of time has passed since the last time the user typed a character. This improves performance and reduces the number of API calls.
Here's how you can implement it:
  • Create the Debounce Function: First, create a debounce function that you can use to wrap your API call or search function. This function will accept a function to execute (`fn`), and the delay in milliseconds (`delay`).
  • Implement the Search Component: Use the debounce function in your search component. You'll use local state to manage the search term and useEffect to handle side effects like API calls.
Here's an example implementation:


    import React, { useState, useEffect } from 'react';

    // Debounce function
    function debounce(fn, delay) {
        let timeoutId;
        return function (...args) {
            if (timeoutId) {
                clearTimeout(timeoutId);
            }
            timeoutId = setTimeout(() => {
                fn(...args);
            }, delay);
        };
    }

    function Search() {
        const [query, setQuery] = useState('');
        const [results, setResults] = useState([]);

        // Wrapped search function with debounce
        const debouncedSearch = debounce((searchQuery) => {
            // Your search API call logic here
            console.log(`Searching for: ${searchQuery}`);
            // Dummy result - replace this with actual API call
            setResults([{ id: 1, name: `Result for ${searchQuery}` }]);
        }, 500);

        useEffect(() => {
            if (query.length > 0) {
                debouncedSearch(query);
            } else {
                setResults([]);
            }
        }, [query]);

        return (
            <div>
                <input
                    type="text"
                    placeholder="Search..."
                    value={query}
                    onChange={(e) => setQuery(e.target.value)}
                />
                <div>
                    {results.map((result) => (
                        <div key={result.id}>{result.name}</div>
                    ))}
                </div>
            </div>
        );
    }

    export default Search;

  • In this example, `debounce` is a higher-order function that takes your search function and returns a new function that is constrained by the delay you specify. The `Search` component updates the search query on every keystroke, but the API call is made only after the user stops typing for the specified delay, thanks to the `debouncedSearch` function.
  • Remember to replace the dummy result generation in `debouncedSearch` with your actual API call logic. This pattern ensures that unnecessary API calls are minimized, improving the performance of your application.
Using TypeScript
  • To convert the example into TypeScript, you'll need to add type annotations to your variables, function parameters, and React component props (if any). Here's how you can rewrite the debounce functionality and search component in TypeScript:

    import React, { useState, useEffect } from 'react';

    // Debounce function
    function debounce(fn: (...args: any[]) => void, delay: number): (...args: any[]) => void {
        let timeoutId: NodeJS.Timeout | null = null;
        return function (...args: any[]) {
            if (timeoutId) {
                clearTimeout(timeoutId);
            }
            timeoutId = setTimeout(() => {
                fn(...args);
            }, delay);
        };
    }

    interface SearchResult {
        id: number;
        name: string;
    }

    function Search(): JSX.Element {
        const [query, setQuery] = useState<string>('');
        const [results, setResults] = useState<SearchResult[]>([]);

        // Wrapped search function with debounce
        const debouncedSearch = debounce((searchQuery: string) => {
            // Your search API call logic here
            console.log(`Searching for: ${searchQuery}`);
            // Dummy result - replace this with actual API call
            setResults([{ id: 1, name: `Result for ${searchQuery}` }]);
        }, 500);

        useEffect(() => {
            if (query.length > 0) {
                debouncedSearch(query);
            } else {
                setResults([]);
            }
        }, [query]);

        return (
            <div>
                <input
                    type="text"
                    placeholder="Search..."
                    value={query}
                    onChange={(e) => setQuery(e.target.value)}
                />
                <div>
                    {results.map((result) => (
                        <div key={result.id}>{result.name}</div>
                    ))}
                </div>
            </div>
        );
    }

    export default Search;


Here's a quick rundown of the changes made to convert the JavaScript example to TypeScript:

  • Type Annotations for State and Function Parameters: Added TypeScript types for state variables (`query`, `results`) and function parameters (in `debounce` and `debouncedSearch`).
  • Type for the 'timeoutId': Changed `timeoutId` from using `number` to `NodeJS.Timeout | null` to correctly type the return value of `setTimeout` in a Node.js environment. This is a common requirement in TypeScript to ensure type safety. If you are targeting a browser environment and the TypeScript compiler complains about `NodeJS.Timeout`, you can use `ReturnType<typeof setTimeout>` instead.
  • Interface for SearchResult: Defined an interface `SearchResult` to describe the shape of the search results. This is used to type the `results` state.
  • With these adjustments, your React component is now properly typed for TypeScript, enhancing code reliability and developer experience by providing compile-time type checking and auto-completion.

No comments:

Post a Comment

Primitive Types in TypeScript

In TypeScript, primitive types are the most basic data types, and they are the building blocks for handling data. They correspond to simple ...