Skip to content

Commit 482925a

Browse files
committed
feat: new article about usedebounce
1 parent 116c01b commit 482925a

9 files changed

+344
-8
lines changed

apps/www/posts/building-better-counters-deep-dive-into-the-usecounter-hook.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: "Building Better Counters: A Deep Dive into the useCounter Hook"
33
date: "2025-07-14"
44
description: "Explore the useCounter hook - a simple yet powerful React hook for managing counter state with increment, decrement, reset, and set operations."
5-
author: "Olivier Colonna"
5+
author: "usehooks.io"
66
tags: ["react", "hooks", "state-management", "counter", "tutorial"]
77
featured: true
88
---

apps/www/posts/mastering-client-side-storage-the-useindexeddb-hook.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "Mastering Client-Side Storage: The useIndexedDB Hook"
33
date: "2025-07-24"
4-
author: "Olivier Colonna"
4+
author: "usehooks.io"
55
description: "Unlock the power of IndexedDB in React with the useIndexedDB hook - featuring automatic database management, transaction handling, and seamless state synchronization for large-scale data storage."
66
tags: ["use-indexed-db", "state", "storage", "indexeddb", "database"]
77
featured: true

apps/www/posts/mastering-persistent-state-the-uselocalstorage-hook.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "Mastering Persistent State: The useLocalStorage Hook"
33
date: "2025-07-16"
4-
author: "Olivier Colonna"
4+
author: "usehooks.io"
55
description: "Learn how to seamlessly persist React state with the useLocalStorage hook - featuring automatic JSON serialization, error handling, and functional updates."
66
tags: ["use-local-storage", "state", "persistence", "localStorage"]
77
featured: true
Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
---
2+
title: "Optimizing Performance with the useDebounce Hook"
3+
date: "2025-08-02"
4+
author: "usehooks.io"
5+
description: "Learn how to optimize React performance and reduce unnecessary API calls with the useDebounce hook - perfect for search inputs, form validation, and real-time updates."
6+
tags: ["use-debounce", "performance", "optimization", "utility"]
7+
featured: true
8+
---
9+
10+
In modern web applications, users expect instant feedback and real-time interactions. However, responding to every keystroke or rapid state change can lead to performance issues and excessive API calls. The [useDebounce](/docs/use-debounce) hook provides an elegant solution by delaying updates until after a specified period of inactivity.
11+
12+
## What is useDebounce?
13+
14+
The [useDebounce](/docs/use-debounce) hook is a utility React hook that delays the propagation of rapidly changing values. It's particularly useful for scenarios where you want to wait for a user to "finish" an action before triggering expensive operations like API calls, complex calculations, or DOM updates.
15+
16+
## Key Features
17+
18+
### ⏱️ Configurable Delay
19+
20+
Set any delay period in milliseconds to control how long the hook waits before updating the debounced value.
21+
22+
### 🎯 Type Safe
23+
24+
Built with TypeScript generics, supporting any data type while maintaining full type safety.
25+
26+
### 🚀 Performance Optimized
27+
28+
Prevents excessive function calls and API requests, significantly improving application performance.
29+
30+
### 🔄 Automatic Cleanup
31+
32+
Handles timer cleanup automatically, preventing memory leaks and ensuring proper component unmounting.
33+
34+
### 📦 Lightweight
35+
36+
Minimal implementation with no external dependencies, adding virtually no bundle size.
37+
38+
## The Implementation
39+
40+
Let's examine how this hook works under the hood:
41+
42+
```typescript
43+
"use client";
44+
45+
import { useState, useEffect } from "react";
46+
47+
export function useDebounce<T>(value: T, delay: number): T {
48+
const [debouncedValue, setDebouncedValue] = useState<T>(value);
49+
50+
useEffect(() => {
51+
const handler = setTimeout(() => {
52+
setDebouncedValue(value);
53+
}, delay);
54+
55+
return () => {
56+
clearTimeout(handler);
57+
};
58+
}, [value, delay]);
59+
60+
return debouncedValue;
61+
}
62+
```
63+
64+
The implementation is elegantly simple:
65+
66+
1. **State Management**: Uses `useState` to maintain the debounced value
67+
2. **Timer Logic**: `useEffect` sets up a timeout that updates the debounced value after the specified delay
68+
3. **Cleanup**: Returns a cleanup function that clears the timeout, preventing memory leaks
69+
4. **Dependency Array**: Re-runs the effect when either `value` or `delay` changes
70+
71+
## Common Use Cases
72+
73+
### Search Input Optimization
74+
75+
One of the most common use cases is debouncing search inputs to avoid making API calls on every keystroke:
76+
77+
```tsx
78+
import { useState, useEffect } from "react";
79+
import { useDebounce } from "@usehooks-io/hooks";
80+
81+
function SearchComponent() {
82+
const [searchTerm, setSearchTerm] = useState("");
83+
const debouncedSearchTerm = useDebounce(searchTerm, 300);
84+
const [results, setResults] = useState([]);
85+
const [loading, setLoading] = useState(false);
86+
87+
// Effect runs only when debounced value changes
88+
useEffect(() => {
89+
if (debouncedSearchTerm) {
90+
setLoading(true);
91+
searchAPI(debouncedSearchTerm)
92+
.then(setResults)
93+
.finally(() => setLoading(false));
94+
} else {
95+
setResults([]);
96+
}
97+
}, [debouncedSearchTerm]);
98+
99+
return (
100+
<div>
101+
<input
102+
value={searchTerm}
103+
onChange={(e) => setSearchTerm(e.target.value)}
104+
placeholder="Search..."
105+
/>
106+
{loading && <p>Searching...</p>}
107+
<ul>
108+
{results.map((result) => (
109+
<li key={result.id}>{result.name}</li>
110+
))}
111+
</ul>
112+
</div>
113+
);
114+
}
115+
```
116+
117+
### Form Validation
118+
119+
Debounce form validation to provide real-time feedback without overwhelming the user:
120+
121+
```tsx
122+
import { useState, useEffect } from "react";
123+
import { useDebounce } from "@usehooks-io/hooks";
124+
125+
function EmailValidation() {
126+
const [email, setEmail] = useState("");
127+
const [isValid, setIsValid] = useState(null);
128+
const debouncedEmail = useDebounce(email, 500);
129+
130+
useEffect(() => {
131+
if (debouncedEmail) {
132+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
133+
setIsValid(emailRegex.test(debouncedEmail));
134+
} else {
135+
setIsValid(null);
136+
}
137+
}, [debouncedEmail]);
138+
139+
return (
140+
<div>
141+
<input
142+
type="email"
143+
value={email}
144+
onChange={(e) => setEmail(e.target.value)}
145+
placeholder="Enter your email"
146+
/>
147+
{isValid === false && (
148+
<p style={{ color: "red" }}>Please enter a valid email</p>
149+
)}
150+
{isValid === true && <p style={{ color: "green" }}>Email looks good!</p>}
151+
</div>
152+
);
153+
}
154+
```
155+
156+
### API Call Optimization
157+
158+
Prevent excessive API calls during rapid state changes:
159+
160+
```tsx
161+
import { useState, useEffect } from "react";
162+
import { useDebounce } from "@usehooks-io/hooks";
163+
164+
function ProductFilters() {
165+
const [filters, setFilters] = useState({
166+
category: "",
167+
minPrice: 0,
168+
maxPrice: 1000,
169+
});
170+
const debouncedFilters = useDebounce(filters, 500);
171+
const [products, setProducts] = useState([]);
172+
173+
useEffect(() => {
174+
// API call only happens after user stops changing filters
175+
fetchProducts(debouncedFilters).then(setProducts);
176+
}, [debouncedFilters]);
177+
178+
const updateFilter = (key: string, value: any) => {
179+
setFilters((prev) => ({ ...prev, [key]: value }));
180+
};
181+
182+
return (
183+
<div>
184+
<select
185+
value={filters.category}
186+
onChange={(e) => updateFilter("category", e.target.value)}
187+
>
188+
<option value="">All Categories</option>
189+
<option value="electronics">Electronics</option>
190+
<option value="clothing">Clothing</option>
191+
</select>
192+
193+
<input
194+
type="range"
195+
min="0"
196+
max="1000"
197+
value={filters.maxPrice}
198+
onChange={(e) => updateFilter("maxPrice", Number(e.target.value))}
199+
/>
200+
201+
<div>
202+
{products.map((product) => (
203+
<div key={product.id}>{product.name}</div>
204+
))}
205+
</div>
206+
</div>
207+
);
208+
}
209+
```
210+
211+
### Window Resize Debouncing
212+
213+
Optimize performance during window resize events:
214+
215+
```tsx
216+
import { useState, useEffect } from "react";
217+
import { useDebounce } from "@usehooks-io/hooks";
218+
219+
function ResponsiveComponent() {
220+
const [windowSize, setWindowSize] = useState({
221+
width: typeof window !== "undefined" ? window.innerWidth : 0,
222+
height: typeof window !== "undefined" ? window.innerHeight : 0,
223+
});
224+
const debouncedWindowSize = useDebounce(windowSize, 250);
225+
226+
useEffect(() => {
227+
const handleResize = () => {
228+
setWindowSize({
229+
width: window.innerWidth,
230+
height: window.innerHeight,
231+
});
232+
};
233+
234+
window.addEventListener("resize", handleResize);
235+
return () => window.removeEventListener("resize", handleResize);
236+
}, []);
237+
238+
// Use debouncedWindowSize for expensive calculations
239+
useEffect(() => {
240+
console.log("Performing expensive layout calculation...");
241+
// Expensive operations only run after resize stops
242+
performExpensiveLayout(debouncedWindowSize);
243+
}, [debouncedWindowSize]);
244+
245+
return (
246+
<div>
247+
<p>
248+
Window size: {debouncedWindowSize.width} x {debouncedWindowSize.height}
249+
</p>
250+
</div>
251+
);
252+
}
253+
```
254+
255+
## Best Practices
256+
257+
### Choose the Right Delay
258+
259+
- **Search inputs**: 300-500ms provides good balance between responsiveness and performance
260+
- **Form validation**: 500-1000ms gives users time to finish typing
261+
- **API calls**: 300-800ms depending on your API response time
262+
- **Resize events**: 100-250ms for smooth visual updates
263+
264+
### Consider User Experience
265+
266+
```tsx
267+
function SearchWithLoading() {
268+
const [searchTerm, setSearchTerm] = useState("");
269+
const [isTyping, setIsTyping] = useState(false);
270+
const debouncedSearchTerm = useDebounce(searchTerm, 300);
271+
272+
useEffect(() => {
273+
if (searchTerm !== debouncedSearchTerm) {
274+
setIsTyping(true);
275+
} else {
276+
setIsTyping(false);
277+
}
278+
}, [searchTerm, debouncedSearchTerm]);
279+
280+
return (
281+
<div>
282+
<input
283+
value={searchTerm}
284+
onChange={(e) => setSearchTerm(e.target.value)}
285+
placeholder="Search..."
286+
/>
287+
{isTyping && <span>Typing...</span>}
288+
</div>
289+
);
290+
}
291+
```
292+
293+
### Combine with Other Hooks
294+
295+
The useDebounce hook works great with other hooks:
296+
297+
```tsx
298+
import { useDebounce, useLocalStorage } from "@usehooks-io/hooks";
299+
300+
function PersistentSearch() {
301+
const [searchTerm, setSearchTerm] = useLocalStorage("searchTerm", "");
302+
const debouncedSearchTerm = useDebounce(searchTerm, 300);
303+
304+
// Search term is automatically persisted and debounced
305+
useEffect(() => {
306+
if (debouncedSearchTerm) {
307+
performSearch(debouncedSearchTerm);
308+
}
309+
}, [debouncedSearchTerm]);
310+
311+
return (
312+
<input
313+
value={searchTerm}
314+
onChange={(e) => setSearchTerm(e.target.value)}
315+
placeholder="Search (persisted)..."
316+
/>
317+
);
318+
}
319+
```
320+
321+
## Performance Benefits
322+
323+
The useDebounce hook can significantly improve your application's performance:
324+
325+
- **Reduced API Calls**: A search input that makes API calls on every keystroke could generate 10+ requests for a single word. With debouncing, this becomes just 1 request.
326+
- **Lower Server Load**: Fewer requests mean less server load and reduced costs.
327+
- **Better User Experience**: Prevents UI flickering and provides smoother interactions.
328+
- **Improved Battery Life**: Fewer operations mean better performance on mobile devices.
329+
330+
## Conclusion
331+
332+
The useDebounce hook is a simple yet powerful tool for optimizing React applications. By delaying updates until after a period of inactivity, it helps reduce unnecessary operations, improve performance, and create better user experiences.
333+
334+
Whether you're building search functionality, form validation, or handling rapid state changes, useDebounce provides an elegant solution that's easy to implement and highly effective.
335+
336+
Try incorporating useDebounce into your next React project and experience the performance benefits firsthand!

apps/www/posts/streamlining-react-development-with-usehooks-cli.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: "Building Better React Apps: A Hands-on Guide to usehooks-cli"
33
date: "2025-07-16"
44
description: "Learn how to supercharge your React development workflow with usehooks-cli through this practical, step-by-step tutorial."
5-
author: "Olivier Colonna"
5+
author: "usehooks.io"
66
tags: ["react", "hooks", "cli", "tutorial", "productivity"]
77
featured: true
88
---

apps/www/posts/the-ultimate-react-array-management-hook.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "The Ultimate React Array Management Hook: useArray"
33
date: "2025-07-14"
4-
author: "Olivier Colonna"
4+
author: "usehooks.io"
55
description: "A comprehensive React hook that provides helper methods for working with array state, including all common array operations optimized with useCallback for performance."
66
tags: ["use-array", "state", "operations"]
77
---

apps/www/posts/use-closure-a-comprehensive-guide.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: "useClosure: A Comprehensive Guide"
33
date: "2025-07-20"
44
description: "Learn how to use the useClosure hook - a powerful React utility for creating and working with JavaScript closures, providing utilities for private state management, memoization, and encapsulation patterns."
5-
author: "Olivier Colonna"
5+
author: "usehooks.io"
66
tags:
77
["react", "hooks", "utility", "useClosure", "tutorial", "guide", "closures"]
88
featured: true

apps/www/posts/use-proxy-a-comprehensive-guide.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: "useProxy: A Comprehensive Guide"
33
date: "2025-07-17"
44
description: "Learn how to use the useProxy hook - a powerful React utility for creating Proxy objects that enable interception and customization of object operations, perfect for implementing reactive objects and data transformations."
5-
author: "Olivier Colonna"
5+
author: "usehooks.io"
66
tags: ["react", "hooks", "state-management", "useProxy", "tutorial", "guide"]
77
featured: true
88
---

0 commit comments

Comments
 (0)