fix(Search): cancel pending debounced onChange when clearing input #3155
+58
−2
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
User description
While researching different design system implementations, I stumbled upon the following bug:
There is a race condition in the Combobox/Search component where typing text and immediately clearing the input would cause the text to reappear with "No results found" message.
Screen.Recording.2025-10-26.at.6.45.30.mov
Reproduction steps:
story/components-combobox--overview)Root cause: The
useDebounceEventhook didn't cancel pending debounced callbacks whenclearValue()was called, allowing stale values to fire after clearing.Solution
useDebounceEventhook viauseRefclearValue()before clearing the valueChanges
Modified Files
packages/core/src/hooks/useDebounceEvent/index.ts- Added cancel logicpackages/core/src/hooks/__tests__/useDebounceEvent.test.ts- Added race condition testpackages/core/src/components/Combobox/__tests__/Combobox.interactions.js- Added integration testTests
should cancel pending debounced onChange when clearValue is calledonImmediateClearBeforeDebounceCompletesTestFuture Improvement Suggestion
Currently, the test waits an arbitrary
500msfor the debounce to complete:Suggestion: Export SEARCH_DEFAULT_DEBOUNCE_RATE constant from a consumer component (e.g combobox) for use in tests:
This makes the relationship explicit and prevents tests from breaking if the default changes.
PR Type
Bug fix, Tests
Description
Fix race condition in Search/Combobox where typing and immediately clearing input caused text to reappear
Store debounced function reference to enable cancellation of pending callbacks
Cancel pending debounced calls when
clearValue()is invokedAdd cleanup effect to cancel debounced callbacks on component unmount
Add unit and integration tests to verify race condition is resolved
Diagram Walkthrough
File Walkthrough
index.ts
Store debounced function reference and add cancellation logicpackages/core/src/hooks/useDebounceEvent/index.ts
debouncedFnRefto store reference to debounced function forcancellation
useMemodebouncedFnRef.current?.cancel()inclearValue()before clearingstate
useDebounceEvent.test.ts
Add unit test for debounce cancellation on clearpackages/core/src/hooks/tests/useDebounceEvent.test.ts
pending debounced callback
onChangeis only called once with empty string, not with stalevalue
vi.runOnlyPendingTimers()to verify no additional callbacks fireCombobox.interactions.js
Add integration test for immediate clear before debouncepackages/core/src/components/Combobox/tests/Combobox.interactions.js
onImmediateClearBeforeDebounceCompletesTestclearing
empty