Skip to content

Commit a87dd3b

Browse files
committed
feat: add useDebouncedState hook
1 parent 310e1ec commit a87dd3b

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

src/useDebouncedState.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { useState, Dispatch, SetStateAction } from 'react'
2+
import useDebouncedCallback from './useDebouncedCallback'
3+
4+
/**
5+
* Similar to `useState`, except the setter function is debounced by
6+
* the specified delay.
7+
*
8+
* ```ts
9+
* const [value, setValue] = useDebouncedState('test', 500)
10+
*
11+
* setValue('test2')
12+
* ```
13+
*
14+
* @param initialState initial state value
15+
* @param delay The milliseconds delay before a new value is set
16+
*/
17+
export default function useDebouncedState<T>(
18+
initialState: T,
19+
delay: number,
20+
): [T, Dispatch<SetStateAction<T>>] {
21+
const [state, setState] = useState(initialState)
22+
const debouncedSetState = useDebouncedCallback<Dispatch<SetStateAction<T>>>(
23+
setState,
24+
delay,
25+
)
26+
return [state, debouncedSetState]
27+
}

test/useDebouncedState.test.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react'
2+
import { mount } from 'enzyme'
3+
import { act } from 'react-dom/test-utils'
4+
import useDebouncedState from '../src/useDebouncedState'
5+
6+
describe('useDebouncedState', () => {
7+
it('should return a function that debounces input callback', () => {
8+
jest.useFakeTimers()
9+
10+
let outerSetValue
11+
12+
function Wrapper() {
13+
const [value, setValue] = useDebouncedState(0, 500)
14+
outerSetValue = setValue
15+
return <span>{value}</span>
16+
}
17+
18+
const wrapper = mount(<Wrapper />)
19+
expect(wrapper.text()).toBe('0')
20+
21+
outerSetValue((cur: number) => cur + 1)
22+
outerSetValue((cur: number) => cur + 1)
23+
outerSetValue((cur: number) => cur + 1)
24+
outerSetValue((cur: number) => cur + 1)
25+
outerSetValue((cur: number) => cur + 1)
26+
27+
expect(wrapper.text()).toBe('0')
28+
29+
act(() => {
30+
jest.runOnlyPendingTimers()
31+
})
32+
33+
expect(wrapper.text()).toBe('1')
34+
})
35+
})

0 commit comments

Comments
 (0)