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>
);
}
USE THROTTLE:
function throttle(fn, delay) {
let lastCall = 0;
return function (...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
fn(...args);
}
};
}
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;
}
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>
type="text"
placeholder="Search here..."
value={query}
onChange={handleChange}
style={{ width: 250, padding: 8 }}
/>
-
{filteredData.map((item) => (
- {item.title} ))}
);
}
Top comments (0)