search-react: fix search bar race
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-search-react': patch
|
||||
---
|
||||
|
||||
Fixed a rare occurrence where a race in the search bar could throw away user input or cause the clear button not to work.
|
||||
@@ -339,7 +339,6 @@ describe('SearchBar', () => {
|
||||
|
||||
value = 'new value';
|
||||
await user.clear(textbox);
|
||||
await waitFor(() => expect(textbox.value).toBe(''));
|
||||
|
||||
// make sure new term is captured
|
||||
await user.type(textbox, value);
|
||||
|
||||
@@ -30,6 +30,7 @@ import React, {
|
||||
KeyboardEvent,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import useDebounce from 'react-use/lib/useDebounce';
|
||||
@@ -88,14 +89,28 @@ export const SearchBarBase: ForwardRefExoticComponent<SearchBarBaseProps> =
|
||||
|
||||
const configApi = useApi(configApiRef);
|
||||
const [value, setValue] = useState<string>('');
|
||||
const forwardedValueRef = useRef<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
setValue(prevValue =>
|
||||
prevValue !== defaultValue ? String(defaultValue) : prevValue,
|
||||
);
|
||||
}, [defaultValue]);
|
||||
setValue(prevValue => {
|
||||
// We only update the value if our current value is the same as it was
|
||||
// for the most recent onChange call. Otherwise it means that the users
|
||||
// has continued typing and we should not replace their input.
|
||||
if (prevValue === forwardedValueRef.current) {
|
||||
return String(defaultValue);
|
||||
}
|
||||
return prevValue;
|
||||
});
|
||||
}, [defaultValue, forwardedValueRef]);
|
||||
|
||||
useDebounce(() => onChange(value), debounceTime, [value]);
|
||||
useDebounce(
|
||||
() => {
|
||||
forwardedValueRef.current = value;
|
||||
onChange(value);
|
||||
},
|
||||
debounceTime,
|
||||
[value],
|
||||
);
|
||||
|
||||
const handleChange = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) => {
|
||||
@@ -115,7 +130,9 @@ export const SearchBarBase: ForwardRefExoticComponent<SearchBarBaseProps> =
|
||||
);
|
||||
|
||||
const handleClear = useCallback(() => {
|
||||
forwardedValueRef.current = '';
|
||||
onChange('');
|
||||
setValue('');
|
||||
if (onClear) {
|
||||
onClear();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { configApiRef } from '@backstage/core-plugin-api';
|
||||
@@ -205,7 +205,6 @@ describe('SearchModal', () => {
|
||||
|
||||
const input = screen.getByLabelText<HTMLInputElement>('Search');
|
||||
await userEvent.clear(input);
|
||||
await waitFor(() => expect(input.value).toBe(''));
|
||||
await userEvent.type(input, 'new term{enter}');
|
||||
|
||||
expect(navigate).toHaveBeenCalledWith('/search?query=new term');
|
||||
|
||||
Reference in New Issue
Block a user