Skip to content
This repository was archived by the owner on Dec 30, 2022. It is now read-only.

Commit c468c0a

Browse files
authored
fix(searchbox): prevent concurrent query updates from state while input is focused (#1133)
1 parent 9ed3802 commit c468c0a

File tree

3 files changed

+27
-0
lines changed

3 files changed

+27
-0
lines changed

src/components/SearchBox.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
:reset-title="resetTitle"
2121
:class-names="classNames"
2222
v-model="currentRefinement"
23+
ref="searchInput"
2324
>
2425
<template
2526
v-slot:loading-indicator
@@ -148,6 +149,14 @@ export default {
148149
this.$emit('update:modelValue', this.model);
149150
this.state.refine(this.model);
150151
}
152+
153+
// we return the local value if the input is focused to avoid
154+
// concurrent updates when typing
155+
const { searchInput } = this.$refs;
156+
if (searchInput && searchInput.isFocused()) {
157+
return this.localValue;
158+
}
159+
151160
return this.model || this.state.query || '';
152161
},
153162
set(val) {

src/components/SearchInput.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ export default {
170170
};
171171
},
172172
methods: {
173+
isFocused() {
174+
return document.activeElement === this.$refs.input;
175+
},
173176
onFormSubmit() {
174177
const input = this.$refs.input;
175178
input.blur();

src/components/__tests__/SearchBox.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,21 @@ test('refine on empty string on form reset', async () => {
147147
expect(state.refine).toHaveBeenCalledWith('');
148148
});
149149

150+
test('keep local query when out of sync and input is focused', async () => {
151+
const state = { ...defaultState, refine: jest.fn() };
152+
__setState(state);
153+
154+
const wrapper = mount(SearchBox, { attachTo: document.body });
155+
const input = wrapper.find('.ais-SearchBox-input');
156+
input.element.focus();
157+
await input.setValue('hello');
158+
159+
await wrapper.setData({ state: { query: 'hel' } });
160+
161+
expect(input.element.value).toBe('hello');
162+
expect(state.refine).toHaveBeenLastCalledWith('hello');
163+
});
164+
150165
test('overriding slots', () => {
151166
__setState({
152167
...defaultState,

0 commit comments

Comments
 (0)