or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

callback-debouncing.mdindex.mdthrottling.mdvalue-debouncing.md

value-debouncing.mddocs/

0

# Value Debouncing

1

2

Value debouncing with `useDebounce` delays value updates until a specified delay has passed without changes. This is perfect for optimizing React component re-renders when dealing with rapidly changing state values like user input, search queries, or form fields.

3

4

## Capabilities

5

6

### useDebounce Hook

7

8

Creates a debounced version of a value that only updates after the specified delay period.

9

10

```typescript { .api }

11

/**

12

* Debounces a value, delaying updates until after delay milliseconds have elapsed

13

* since the last time the value changed.

14

*

15

* @param value - The value to debounce

16

* @param delay - The number of milliseconds to delay

17

* @param options - Optional configuration object

18

* @returns Tuple of [debouncedValue, controlFunctions]

19

*/

20

function useDebounce<T>(

21

value: T,

22

delay: number,

23

options?: {

24

maxWait?: number;

25

leading?: boolean;

26

trailing?: boolean;

27

equalityFn?: (left: T, right: T) => boolean;

28

}

29

): [T, DebouncedState<(value: T) => void>];

30

```

31

32

**Parameters:**

33

34

- `value: T` - The value to debounce (can be any type)

35

- `delay: number` - Delay in milliseconds before updating the debounced value

36

- `options` - Optional configuration object with:

37

- `maxWait?: number` - Maximum time the value is allowed to be delayed before it's updated

38

- `leading?: boolean` - If true, updates the value immediately on first change, then debounces subsequent changes

39

- `trailing?: boolean` - If true (default), updates the value after the delay period

40

- `equalityFn?: (left: T, right: T) => boolean` - Custom equality function to determine if the value has changed (defaults to `===`)

41

42

**Returns:**

43

- `[T, DebouncedState]` - A tuple containing the debounced value and control functions (`cancel`, `flush`, `isPending`)

44

45

**Usage Examples:**

46

47

```typescript

48

import React, { useState } from 'react';

49

import { useDebounce } from 'use-debounce';

50

51

// Basic text input debouncing

52

function SearchInput() {

53

const [searchTerm, setSearchTerm] = useState('');

54

const [debouncedSearchTerm] = useDebounce(searchTerm, 500);

55

56

// This effect will only run when debouncedSearchTerm changes

57

React.useEffect(() => {

58

if (debouncedSearchTerm) {

59

// Perform API search

60

console.log('Searching for:', debouncedSearchTerm);

61

}

62

}, [debouncedSearchTerm]);

63

64

return (

65

<input

66

type="text"

67

value={searchTerm}

68

onChange={(e) => setSearchTerm(e.target.value)}

69

placeholder="Search..."

70

/>

71

);

72

}

73

74

// Leading option - immediate first update

75

function InstantSearch() {

76

const [query, setQuery] = useState('');

77

const [debouncedQuery] = useDebounce(query, 1000, { leading: true });

78

79

// First change updates immediately, subsequent changes are debounced

80

return (

81

<div>

82

<input value={query} onChange={(e) => setQuery(e.target.value)} />

83

<p>Debounced: {debouncedQuery}</p>

84

</div>

85

);

86

}

87

88

// With control functions

89

function ControlledDebounce() {

90

const [text, setText] = useState('');

91

const [debouncedText, { cancel, flush, isPending }] = useDebounce(text, 1000);

92

93

return (

94

<div>

95

<input value={text} onChange={(e) => setText(e.target.value)} />

96

<p>Text: {text}</p>

97

<p>Debounced: {debouncedText}</p>

98

<button onClick={cancel}>Cancel</button>

99

<button onClick={flush}>Flush Now</button>

100

<p>Pending: {isPending() ? 'Yes' : 'No'}</p>

101

</div>

102

);

103

}

104

105

// Custom equality function for objects

106

function ObjectDebounce() {

107

const [user, setUser] = useState({ name: '', email: '' });

108

const [debouncedUser] = useDebounce(

109

user,

110

500,

111

{

112

equalityFn: (prev, next) =>

113

prev.name === next.name && prev.email === next.email

114

}

115

);

116

117

return (

118

<div>

119

<input

120

value={user.name}

121

onChange={(e) => setUser({ ...user, name: e.target.value })}

122

placeholder="Name"

123

/>

124

<input

125

value={user.email}

126

onChange={(e) => setUser({ ...user, email: e.target.value })}

127

placeholder="Email"

128

/>

129

<p>Debounced: {JSON.stringify(debouncedUser)}</p>

130

</div>

131

);

132

}

133

134

// MaxWait option

135

function MaxWaitExample() {

136

const [value, setValue] = useState('');

137

const [debouncedValue] = useDebounce(value, 500, { maxWait: 2000 });

138

139

// Will update after 500ms of no changes, or after 2000ms maximum

140

return (

141

<div>

142

<input value={value} onChange={(e) => setValue(e.target.value)} />

143

<p>Debounced (max 2s): {debouncedValue}</p>

144

</div>

145

);

146

}

147

```

148

149

### Control Functions

150

151

The debounced state includes control functions for managing the debounce behavior:

152

153

```typescript { .api }

154

interface ControlFunctions<ReturnT> {

155

/** Cancel any pending debounced updates */

156

cancel: () => void;

157

/** Immediately execute any pending debounced updates */

158

flush: () => ReturnT | undefined;

159

/** Check if there are any pending debounced updates */

160

isPending: () => boolean;

161

}

162

```

163

164

**Control Methods:**

165

166

- `cancel()` - Cancels any pending debounced value updates

167

- `flush()` - Immediately applies any pending debounced value updates

168

- `isPending()` - Returns `true` if there's a pending debounced update, `false` otherwise

169

170

## Common Patterns

171

172

### Form Input Optimization

173

174

```typescript

175

function OptimizedForm() {

176

const [formData, setFormData] = useState({

177

username: '',

178

email: '',

179

message: ''

180

});

181

182

// Debounce the entire form object

183

const [debouncedFormData] = useDebounce(formData, 300);

184

185

// Only validate when debounced data changes

186

React.useEffect(() => {

187

validateForm(debouncedFormData);

188

}, [debouncedFormData]);

189

190

return (

191

<form>

192

<input

193

value={formData.username}

194

onChange={(e) => setFormData(prev => ({

195

...prev,

196

username: e.target.value

197

}))}

198

/>

199

{/* More form fields... */}

200

</form>

201

);

202

}

203

```

204

205

### API Request Debouncing

206

207

```typescript

208

function AutoSuggest() {

209

const [query, setQuery] = useState('');

210

const [suggestions, setSuggestions] = useState([]);

211

const [debouncedQuery] = useDebounce(query, 400);

212

213

React.useEffect(() => {

214

if (debouncedQuery.length > 2) {

215

fetch(`/api/suggestions?q=${debouncedQuery}`)

216

.then(res => res.json())

217

.then(setSuggestions);

218

} else {

219

setSuggestions([]);

220

}

221

}, [debouncedQuery]);

222

223

return (

224

<div>

225

<input

226

value={query}

227

onChange={(e) => setQuery(e.target.value)}

228

/>

229

<ul>

230

{suggestions.map(suggestion => (

231

<li key={suggestion.id}>{suggestion.text}</li>

232

))}

233

</ul>

234

</div>

235

);

236

}

237

```