DEV Community

ZeeshanAli-0704
ZeeshanAli-0704

Posted on • Edited on

Debounce in React Functional Component

import React, { useState, useMemo } from "react";
import { useEffect } from "react";

export default function SearchExample() {
  const [query, setQuery] = useState("");
  const [results, setResults] = useState([]);
  const [filteredData, setFilteredData] = useState([]);

  function debounce(fn, delay) {
    let timeout;
    return function (...args) {
      var context = this;
      clearTimeout(timeout);
      timeout = setTimeout(() => {
        fn.apply(context, args);
      }, delay);
    };
  }

  const getTodosViaAPI = () => {
    fetch("https://jsonplaceholder.typicode.com/todos")
      .then((response) => response.json())
      .then((finalData) => {
        setFilteredData(finalData);
        setResults(finalData);
      })
      .catch((err) => console.log(err));
  };

  useEffect(() => {
    getTodosViaAPI();
  }, []);

  const performSearch = async (text) => {
    // If empty search, reset original data
    if (!text.trim()) {
      setFilteredData(results);
      return;
    }

    const updated = results.filter((item) =>
      item.title.toLowerCase().includes(text.toLowerCase())
    );

    setFilteredData(updated);
  };

  // Make debounced version of search
  const debouncedSearch = debounce(performSearch, 3000);

  const handleChange = (e) => {
    const value = e.target.value;
    // UI updates instantly
    setQuery(value);
    // Debounced search
    debouncedSearch(value);
  };

  return (
    <div style={{ padding: 20 }}>
      <h2>Search Example</h2>

      <input
        type="text"
        placeholder="Search here..."
        value={query}
        onChange={handleChange}
        style={{ width: 250, padding: 8 }}
      />

      <hr />

      <h3>Results:</h3>
      {filteredData.length === 0 && <div>No Data Found...</div>}

      <ul>
        {filteredData.map((item, i) => (
          <li key={i}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
}


Enter fullscreen mode Exit fullscreen mode

USE THROTTLE:




function throttle(fn, delay) {
  let lastCall = 0;

  return function (...args) {
    const now = Date.now();

    if (now - lastCall >= delay) {
      lastCall = now;
      fn(...args);
    }
  };
}
Enter fullscreen mode Exit fullscreen mode
import React, { useState, useMemo, useEffect } from "react";

export default function SearchExample() {
const [query, setQuery] = useState("");
const [results, setResults] = useState([]);
const [filteredData, setFilteredData] = useState([]);

// ---- Config flag ----
const useThrottle = false; // true = throttle, false = debounce

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

// Throttle function
function throttle(fn, delay) {
let lastCall = 0;
return function (...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
fn(...args);
}
};
}

const getTodosViaAPI = () => {
fetch("[https://jsonplaceholder.typicode.com/todos](https://jsonplaceholder.typicode.com/todos)")
.then((response) => response.json())
.then((finalData) => {
setResults(finalData);
setFilteredData(finalData);
});
};

useEffect(() => {
getTodosViaAPI();
}, []);

const performSearch = (text) => {
if (!text.trim()) {
setFilteredData(results);
return;
}

Enter fullscreen mode Exit fullscreen mode

const updated = results.filter((item) =>
item.title.toLowerCase().includes(text.toLowerCase())
);
setFilteredData(updated);


};

// Create either throttle or debounce based on flag
const debouncedOrThrottledSearch = useMemo(() => {
return useThrottle
? throttle(performSearch, 600)
: debounce(performSearch, 600);
}, [results, useThrottle]);

const handleChange = (e) => {
const value = e.target.value;
setQuery(value);
debouncedOrThrottledSearch(value);
};

return (
<div style={{ padding: 20 }}> <h2>Search Example ({useThrottle ? "Throttle" : "Debounce"})</h2>

Enter fullscreen mode Exit fullscreen mode

type="text"
placeholder="Search here..."
value={query}
onChange={handleChange}
style={{ width: 250, padding: 8 }}
/>

    {filteredData.map((item) => (
  • {item.title}
  • ))}



);
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)